blob: 789834236b049f9d3896cdb291175342b2b3aae4 [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 Hackborn2269d1572010-02-24 19:54:22 -080033import com.android.internal.util.XmlUtils;
Kenny Rootcf0b38c2011-03-22 14:17:59 -070034import com.android.server.DeviceStorageMonitorService;
35import com.android.server.EventLogTags;
36import com.android.server.IntentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Jason parksa3cdaa52011-01-13 14:15:43 -060038import org.xmlpull.v1.XmlPullParser;
39import org.xmlpull.v1.XmlPullParserException;
Jason parksa3cdaa52011-01-13 14:15:43 -060040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.app.ActivityManagerNative;
42import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080043import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080044import android.app.backup.IBackupManager;
Kenny Root5ab21572011-07-27 11:11:19 -070045import android.content.BroadcastReceiver;
Jason parksa3cdaa52011-01-13 14:15:43 -060046import android.content.ComponentName;
Kenny Root27989422011-02-23 16:28:26 -080047import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070048import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.Intent;
50import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070051import android.content.IntentSender;
Jason parks1125d782011-01-12 09:47:26 -060052import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060053import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.content.pm.ActivityInfo;
55import android.content.pm.ApplicationInfo;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -070056import android.content.pm.ContainerEncryptionParams;
Dianne Hackborn49237342009-08-27 20:08:01 -070057import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.content.pm.IPackageDataObserver;
59import android.content.pm.IPackageDeleteObserver;
60import android.content.pm.IPackageInstallObserver;
61import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080062import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.content.pm.IPackageStatsObserver;
64import android.content.pm.InstrumentationInfo;
65import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080066import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060068import android.content.pm.PackageParser;
Kenny Root27989422011-02-23 16:28:26 -080069import android.content.pm.PackageStats;
Kenny Root0e2c0f32011-04-15 17:50:10 -070070import android.content.pm.ParceledListSlice;
Jason parksa3cdaa52011-01-13 14:15:43 -060071import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080072import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.content.pm.ProviderInfo;
74import android.content.pm.ResolveInfo;
75import android.content.pm.ServiceInfo;
76import android.content.pm.Signature;
Amith Yamasani0b285492011-04-14 17:35:23 -070077import android.content.pm.UserInfo;
Kenny Root5ab21572011-07-27 11:11:19 -070078import android.content.pm.ManifestDigest;
Kenny Root0aaa0d92011-09-12 16:42:55 -070079import android.content.pm.VerifierDeviceIdentity;
Kenny Root05ca4c92011-09-15 10:36:25 -070080import android.content.pm.VerifierInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.net.Uri;
82import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070083import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -080085import android.os.Environment;
86import android.os.FileObserver;
87import android.os.FileUtils;
88import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080090import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070091import android.os.Looper;
92import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.os.ParcelFileDescriptor;
95import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -080096import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.ServiceManager;
98import android.os.SystemClock;
99import android.os.SystemProperties;
Amith Yamasani742a6712011-05-04 14:49:28 -0700100import android.os.UserId;
Jeff Sharkeyf5385772012-05-11 14:04:41 -0700101import android.provider.Settings.Secure;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800102import android.security.SystemKeyStore;
Kenny Root27989422011-02-23 16:28:26 -0800103import android.util.DisplayMetrics;
104import android.util.EventLog;
105import android.util.Log;
106import android.util.LogPrinter;
107import android.util.Slog;
108import android.util.SparseArray;
109import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.Display;
111import android.view.WindowManager;
112
113import java.io.File;
114import java.io.FileDescriptor;
115import java.io.FileInputStream;
116import java.io.FileNotFoundException;
117import java.io.FileOutputStream;
118import java.io.FileReader;
119import java.io.FilenameFilter;
120import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800122import java.security.NoSuchAlgorithmException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700123import java.security.PublicKey;
124import java.security.cert.CertificateException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800125import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126import java.util.ArrayList;
127import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700128import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129import java.util.Collections;
130import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800131import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132import java.util.HashMap;
133import java.util.HashSet;
134import java.util.Iterator;
135import java.util.List;
136import java.util.Map;
Amith Yamasani13593602012-03-22 16:16:17 -0700137import java.util.Map.Entry;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
Kenny Root66269ea2011-07-12 14:14:01 -0700140import libcore.io.ErrnoException;
Kenny Root3f99afc2012-04-14 10:13:10 -0700141import libcore.io.IoUtils;
Kenny Root66269ea2011-07-12 14:14:01 -0700142import libcore.io.Libcore;
143
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700144/**
145 * Keep track of all those .apks everywhere.
146 *
147 * This is very central to the platform's security; please run the unit
148 * tests whenever making modifications here:
149 *
150mmm frameworks/base/tests/AndroidTests
151adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
152adb 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 -0700153 *
154 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700155 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700156public class PackageManagerService extends IPackageManager.Stub {
157 static final String TAG = "PackageManager";
158 static final boolean DEBUG_SETTINGS = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 private static final boolean DEBUG_PREFERRED = false;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700160 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800161 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800162 private static final boolean DEBUG_REMOVE = false;
163 private static final boolean DEBUG_SHOW_INFO = false;
164 private static final boolean DEBUG_PACKAGE_INFO = false;
165 private static final boolean DEBUG_INTENT_MATCHING = false;
166 private static final boolean DEBUG_PACKAGE_SCANNING = false;
167 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
Kenny Root05ca4c92011-09-15 10:36:25 -0700168 private static final boolean DEBUG_VERIFY = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400171 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700172 private static final int NFC_UID = Process.NFC_UID;
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 boolean GET_CERTIFICATES = true;
175
176 private static final int REMOVE_EVENTS =
177 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
178 private static final int ADD_EVENTS =
179 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
180
181 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800182 // Suffix used during package installation when copying/moving
183 // package apks to install directory.
184 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
186 static final int SCAN_MONITOR = 1<<0;
187 static final int SCAN_NO_DEX = 1<<1;
188 static final int SCAN_FORCE_DEX = 1<<2;
189 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800190 static final int SCAN_NEW_INSTALL = 1<<4;
191 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700192 static final int SCAN_UPDATE_TIME = 1<<6;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700193 static final int SCAN_DEFER_DEX = 1<<7;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700194 static final int SCAN_BOOTING = 1<<8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700196 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700197
Kenny Root5ab21572011-07-27 11:11:19 -0700198 /**
199 * Whether verification is enabled by default.
200 */
Brett Chabotae05e862011-08-24 18:38:26 -0700201 // STOPSHIP: change this to true
202 private static final boolean DEFAULT_VERIFY_ENABLE = false;
Kenny Root5ab21572011-07-27 11:11:19 -0700203
204 /**
205 * The default maximum time to wait for the verification agent to return in
206 * milliseconds.
207 */
rich canningsaa8513e2012-05-21 16:15:23 -0700208 private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Kenny Root5ab21572011-07-27 11:11:19 -0700209
rich canningsa6cfe522012-05-21 15:50:56 -0700210 /**
211 * The default response for package verification timeout.
212 *
213 * This can be either PackageManager.VERIFICATION_ALLOW or
214 * PackageManager.VERIFICATION_REJECT.
215 */
216 private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
217
Kenny Root11128572010-10-11 10:51:32 -0700218 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
219
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800220 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700221 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800222 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700223
Kenny Root05ca4c92011-09-15 10:36:25 -0700224 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
225
Kenny Root85387d72010-08-26 10:13:11 -0700226 private static final String LIB_DIR_NAME = "lib";
227
Kenny Rootc78a8072010-07-27 15:18:38 -0700228 static final String mTempContainerPrefix = "smdl2tmp";
229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
231 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700232 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233
Dianne Hackborn851a5412009-05-08 12:06:44 -0700234 final int mSdkVersion = Build.VERSION.SDK_INT;
235 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
236 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 final Context mContext;
239 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700240 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700241 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 final DisplayMetrics mMetrics;
243 final int mDefParseFlags;
244 final String[] mSeparateProcesses;
245
246 // This is where all application persistent data goes.
247 final File mAppDataDir;
248
Amith Yamasani0b285492011-04-14 17:35:23 -0700249 // This is where all application persistent data goes for secondary users.
250 final File mUserAppDataDir;
251
Kenny Root51a573c2012-05-17 13:30:28 -0700252 /** The location for ASEC container files on internal storage. */
253 final String mAsecInternalPath;
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 // This is the object monitoring the framework dir.
256 final FileObserver mFrameworkInstallObserver;
257
258 // This is the object monitoring the system app dir.
259 final FileObserver mSystemInstallObserver;
260
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700261 // This is the object monitoring the system app dir.
262 final FileObserver mVendorInstallObserver;
263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // This is the object monitoring mAppInstallDir.
265 final FileObserver mAppInstallObserver;
266
267 // This is the object monitoring mDrmAppPrivateInstallDir.
268 final FileObserver mDrmAppInstallObserver;
269
270 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
271 // LOCK HELD. Can be called with mInstallLock held.
272 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 final File mFrameworkDir;
275 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700276 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700278 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
280 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
281 // apps.
282 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 // Lock for state used when installing and doing other long running
287 // operations. Methods that must be called with this lock held have
288 // the prefix "LI".
289 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 // These are the directories in the 3rd party applications installed dir
292 // that we have currently loaded packages from. Keys are the application's
293 // installed zip file (absolute codePath), and values are Package.
294 final HashMap<String, PackageParser.Package> mAppDirs =
295 new HashMap<String, PackageParser.Package>();
296
297 // Information for the parser to write more useful error messages.
298 File mScanningPath;
299 int mLastScanError;
300
301 final int[] mOutPermissions = new int[3];
302
303 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 // Keys are String (package name), values are Package. This also serves
306 // as the lock for the global state. Methods that must be called with
307 // this lock held have the prefix "LP".
308 final HashMap<String, PackageParser.Package> mPackages =
309 new HashMap<String, PackageParser.Package>();
310
311 final Settings mSettings;
312 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313
314 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
315 int[] mGlobalGids;
316
317 // These are the built-in uid -> permission mappings that were read from the
318 // etc/permissions.xml file.
319 final SparseArray<HashSet<String>> mSystemPermissions =
320 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 // These are the built-in shared libraries that were read from the
323 // etc/permissions.xml file.
324 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800325
Dianne Hackborn49237342009-08-27 20:08:01 -0700326 // Temporary for building the final shared libraries for an .apk.
327 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800328
Dianne Hackborn49237342009-08-27 20:08:01 -0700329 // These are the features this devices supports that were read from the
330 // etc/permissions.xml file.
331 final HashMap<String, FeatureInfo> mAvailableFeatures =
332 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 // All available activities, for your resolving pleasure.
335 final ActivityIntentResolver mActivities =
336 new ActivityIntentResolver();
337
338 // All available receivers, for your resolving pleasure.
339 final ActivityIntentResolver mReceivers =
340 new ActivityIntentResolver();
341
342 // All available services, for your resolving pleasure.
343 final ServiceIntentResolver mServices = new ServiceIntentResolver();
344
345 // Keys are String (provider class name), values are Provider.
346 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
347 new HashMap<ComponentName, PackageParser.Provider>();
348
349 // Mapping from provider base names (first directory in content URI codePath)
350 // to the provider information.
351 final HashMap<String, PackageParser.Provider> mProviders =
352 new HashMap<String, PackageParser.Provider>();
353
354 // Mapping from instrumentation class names to info about them.
355 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
356 new HashMap<ComponentName, PackageParser.Instrumentation>();
357
358 // Mapping from permission names to info about them.
359 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
360 new HashMap<String, PackageParser.PermissionGroup>();
361
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800362 // Packages whose data we have transfered into another package, thus
363 // should no longer exist.
364 final HashSet<String> mTransferedPackages = new HashSet<String>();
365
Dianne Hackborn854060af2009-07-09 18:14:31 -0700366 // Broadcast actions that are only available to the system.
367 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800368
Kenny Root5ab21572011-07-27 11:11:19 -0700369 /** List of packages waiting for verification. */
Kenny Root05ca4c92011-09-15 10:36:25 -0700370 final SparseArray<PackageVerificationState> mPendingVerification
371 = new SparseArray<PackageVerificationState>();
Kenny Root5ab21572011-07-27 11:11:19 -0700372
Dianne Hackborn661cd522011-08-22 00:26:20 -0700373 final ArrayList<PackageParser.Package> mDeferredDexOpt =
374 new ArrayList<PackageParser.Package>();
375
Kenny Root5ab21572011-07-27 11:11:19 -0700376 /** Token for keys in mPendingVerification. */
377 private int mPendingVerificationToken = 0;
378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 boolean mSystemReady;
380 boolean mSafeMode;
381 boolean mHasSystemUidErrors;
382
383 ApplicationInfo mAndroidApplication;
384 final ActivityInfo mResolveActivity = new ActivityInfo();
385 final ResolveInfo mResolveInfo = new ResolveInfo();
386 ComponentName mResolveComponentName;
387 PackageParser.Package mPlatformPackage;
388
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700389 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800390 final HashMap<String, ArrayList<String>> mPendingBroadcasts
391 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800392 // Service Connection to remote media container service to copy
393 // package uri's from external media onto secure containers
394 // or internal storage.
395 private IMediaContainerService mContainerService = null;
396
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700397 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800398 static final int MCS_BOUND = 3;
399 static final int END_COPY = 4;
400 static final int INIT_COPY = 5;
401 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800402 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800403 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800404 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800405 static final int MCS_RECONNECT = 10;
406 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700407 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700408 static final int WRITE_SETTINGS = 13;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700409 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
Kenny Root5ab21572011-07-27 11:11:19 -0700410 static final int PACKAGE_VERIFIED = 15;
411 static final int CHECK_PENDING_VERIFICATION = 16;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700412
413 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800414
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700415 // Delay time in millisecs
416 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800417
Amith Yamasani13593602012-03-22 16:16:17 -0700418 static UserManager sUserManager;
Amith Yamasani0b285492011-04-14 17:35:23 -0700419
Amith Yamasani483f3b02012-03-13 16:08:00 -0700420 // Stores a list of users whose package restrictions file needs to be updated
421 private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
422
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800423 final private DefaultContainerConnection mDefContainerConn =
424 new DefaultContainerConnection();
425 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800426 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800427 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800428 IMediaContainerService imcs =
429 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800430 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800431 }
432
433 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800434 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800435 }
436 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700437
Christopher Tate1bb69062010-02-19 17:02:12 -0800438 // Recordkeeping of restore-after-install operations that are currently in flight
439 // between the Package Manager and the Backup Manager
440 class PostInstallData {
441 public InstallArgs args;
442 public PackageInstalledInfo res;
443
444 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
445 args = _a;
446 res = _r;
447 }
448 };
449 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
450 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
451
Kenny Root05ca4c92011-09-15 10:36:25 -0700452 private final String mRequiredVerifierPackage;
453
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700454 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800455 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800456 final ArrayList<HandlerParams> mPendingInstalls =
457 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800458
459 private boolean connectToService() {
460 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
461 " DefaultContainerService");
462 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700463 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800464 if (mContext.bindService(service, mDefContainerConn,
465 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700466 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800467 mBound = true;
468 return true;
469 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700470 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800471 return false;
472 }
473
474 private void disconnectService() {
475 mContainerService = null;
476 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700477 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800478 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700479 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800480 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800481
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700482 PackageHandler(Looper looper) {
483 super(looper);
484 }
Dianne Hackborn7d608422011-08-07 16:24:18 -0700485
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700486 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700487 try {
488 doHandleMessage(msg);
489 } finally {
490 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
491 }
492 }
493
494 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700495 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800496 case INIT_COPY: {
Kenny Root5ab21572011-07-27 11:11:19 -0700497 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800498 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800499 int idx = mPendingInstalls.size();
Kenny Root5ab21572011-07-27 11:11:19 -0700500 if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800501 // If a bind was already initiated we dont really
502 // need to do anything. The pending install
503 // will be processed later on.
504 if (!mBound) {
505 // If this is the only one pending we might
506 // have to bind to the service again.
507 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800508 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800509 params.serviceError();
510 return;
511 } else {
512 // Once we bind to the service, the first
513 // pending request will be processed.
514 mPendingInstalls.add(idx, params);
515 }
516 } else {
517 mPendingInstalls.add(idx, params);
518 // Already bound to the service. Just make
519 // sure we trigger off processing the first request.
520 if (idx == 0) {
521 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800522 }
523 }
524 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800525 }
526 case MCS_BOUND: {
Kenny Root5ab21572011-07-27 11:11:19 -0700527 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800528 if (msg.obj != null) {
529 mContainerService = (IMediaContainerService) msg.obj;
530 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800531 if (mContainerService == null) {
532 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800533 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800534 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800535 // Indicate service bind error
536 params.serviceError();
537 }
538 mPendingInstalls.clear();
539 } else if (mPendingInstalls.size() > 0) {
540 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800541 if (params != null) {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700542 if (params.startCopy()) {
543 // We are done... look for more work or to
544 // go idle.
545 if (DEBUG_SD_INSTALL) Log.i(TAG,
546 "Checking for more work or unbind...");
547 // Delete pending install
548 if (mPendingInstalls.size() > 0) {
549 mPendingInstalls.remove(0);
550 }
551 if (mPendingInstalls.size() == 0) {
552 if (mBound) {
553 if (DEBUG_SD_INSTALL) Log.i(TAG,
554 "Posting delayed MCS_UNBIND");
555 removeMessages(MCS_UNBIND);
556 Message ubmsg = obtainMessage(MCS_UNBIND);
557 // Unbind after a little delay, to avoid
558 // continual thrashing.
559 sendMessageDelayed(ubmsg, 10000);
560 }
561 } else {
562 // There are more pending requests in queue.
563 // Just post MCS_BOUND message to trigger processing
564 // of next pending install.
565 if (DEBUG_SD_INSTALL) Log.i(TAG,
566 "Posting MCS_BOUND for next woek");
567 mHandler.sendEmptyMessage(MCS_BOUND);
568 }
569 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800570 }
571 } else {
572 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800573 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800574 }
575 break;
576 }
Kenny Root5ab21572011-07-27 11:11:19 -0700577 case MCS_RECONNECT: {
578 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800579 if (mPendingInstalls.size() > 0) {
580 if (mBound) {
581 disconnectService();
582 }
583 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800584 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800585 for (HandlerParams params : mPendingInstalls) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800586 // Indicate service bind error
587 params.serviceError();
588 }
589 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800590 }
591 }
592 break;
593 }
Kenny Root5ab21572011-07-27 11:11:19 -0700594 case MCS_UNBIND: {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700595 // If there is no actual work left, then time to unbind.
Kenny Root5ab21572011-07-27 11:11:19 -0700596 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
597
598 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800599 if (mBound) {
Kenny Root5ab21572011-07-27 11:11:19 -0700600 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
601
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800602 disconnectService();
603 }
Kenny Root5ab21572011-07-27 11:11:19 -0700604 } else if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800605 // There are more pending requests in queue.
606 // Just post MCS_BOUND message to trigger processing
607 // of next pending install.
608 mHandler.sendEmptyMessage(MCS_BOUND);
609 }
Kenny Root5ab21572011-07-27 11:11:19 -0700610
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800611 break;
612 }
613 case MCS_GIVE_UP: {
Kenny Root5ab21572011-07-27 11:11:19 -0700614 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700615 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800616 break;
617 }
Kenny Root5ab21572011-07-27 11:11:19 -0700618 case SEND_PENDING_BROADCAST: {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800619 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700620 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700621 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700622 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700623 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700624 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800625 if (mPendingBroadcasts == null) {
626 return;
627 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700628 size = mPendingBroadcasts.size();
629 if (size <= 0) {
630 // Nothing to be done. Just return
631 return;
632 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800633 packages = new String[size];
634 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700635 uids = new int[size];
Andy McFadden2f362292012-01-20 14:43:38 -0800636 Iterator<Map.Entry<String, ArrayList<String>>>
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800637 it = mPendingBroadcasts.entrySet().iterator();
638 int i = 0;
639 while (it.hasNext() && i < size) {
Andy McFadden2f362292012-01-20 14:43:38 -0800640 Map.Entry<String, ArrayList<String>> ent = it.next();
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800641 packages[i] = ent.getKey();
642 components[i] = ent.getValue();
643 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -0700644 uids[i] = (ps != null) ? ps.appId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800645 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700646 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800647 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700648 mPendingBroadcasts.clear();
649 }
650 // Send broadcasts
651 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700652 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700653 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700654 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700655 break;
656 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800657 case START_CLEANING_PACKAGE: {
658 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700659 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800660 synchronized (mPackages) {
661 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
662 mSettings.mPackagesToBeCleaned.add(packageName);
663 }
664 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700665 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800666 startCleaningPackages();
667 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800668 case POST_INSTALL: {
669 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
670 PostInstallData data = mRunningInstalls.get(msg.arg1);
671 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700672 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800673
674 if (data != null) {
675 InstallArgs args = data.args;
676 PackageInstalledInfo res = data.res;
677
678 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700679 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800680 Bundle extras = new Bundle(1);
681 extras.putInt(Intent.EXTRA_UID, res.uid);
682 final boolean update = res.removedInfo.removedPackage != null;
683 if (update) {
684 extras.putBoolean(Intent.EXTRA_REPLACING, true);
685 }
686 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
687 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700688 extras, null, null, UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800689 if (update) {
690 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
691 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700692 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800693 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
694 null, null,
Amith Yamasani13593602012-03-22 16:16:17 -0700695 res.pkg.applicationInfo.packageName, null,
696 UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800697 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700698 if (res.removedInfo.args != null) {
699 // Remove the replaced package's older resources safely now
700 deleteOld = true;
701 }
Matt Finifterf8a98ed2012-05-14 15:43:34 -0700702
703 // Log current value of "unknown sources" setting
704 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
705 getUnknownSourcesSettings());
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700706 }
707 // Force a gc to clear up things
708 Runtime.getRuntime().gc();
709 // We delete after a gc for applications on sdcard.
710 if (deleteOld) {
711 synchronized (mInstallLock) {
712 res.removedInfo.args.doPostDeleteLI(true);
713 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800714 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800715 if (args.observer != null) {
716 try {
717 args.observer.packageInstalled(res.name, res.returnCode);
718 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800719 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800720 }
721 }
722 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800723 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800724 }
725 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700726 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700727 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
728 boolean reportStatus = msg.arg1 == 1;
729 boolean doGc = msg.arg2 == 1;
730 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
731 if (doGc) {
732 // Force a gc to clear up stale containers.
733 Runtime.getRuntime().gc();
734 }
735 if (msg.obj != null) {
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700736 @SuppressWarnings("unchecked")
Kenny Root6dceb882012-04-12 14:23:49 -0700737 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700738 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
739 // Unload containers
740 unloadAllContainers(args);
741 }
742 if (reportStatus) {
743 try {
744 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
745 PackageHelper.getMountService().finishMediaUpdate();
746 } catch (RemoteException e) {
747 Log.e(TAG, "MountService not running?");
748 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700749 }
750 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700751 case WRITE_SETTINGS: {
752 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
753 synchronized (mPackages) {
754 removeMessages(WRITE_SETTINGS);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700755 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
Kenny Root447106f2011-03-23 11:00:15 -0700756 mSettings.writeLPr();
Amith Yamasani483f3b02012-03-13 16:08:00 -0700757 mDirtyUsers.clear();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700758 }
759 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
760 } break;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700761 case WRITE_PACKAGE_RESTRICTIONS: {
Dianne Hackborne7f97212011-02-24 14:40:20 -0800762 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
763 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -0700764 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
765 for (int userId : mDirtyUsers) {
766 mSettings.writePackageRestrictionsLPr(userId);
767 }
768 mDirtyUsers.clear();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800769 }
770 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
771 } break;
Kenny Root5ab21572011-07-27 11:11:19 -0700772 case CHECK_PENDING_VERIFICATION: {
773 final int verificationId = msg.arg1;
Kenny Root05ca4c92011-09-15 10:36:25 -0700774 final PackageVerificationState state = mPendingVerification.get(verificationId);
Kenny Root5ab21572011-07-27 11:11:19 -0700775
Kenny Root05ca4c92011-09-15 10:36:25 -0700776 if (state != null) {
777 final InstallArgs args = state.getInstallArgs();
Kenny Roota503a0f2011-10-03 14:45:28 -0700778 Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
Kenny Root5ab21572011-07-27 11:11:19 -0700779 mPendingVerification.remove(verificationId);
780
rich canningsa6cfe522012-05-21 15:50:56 -0700781 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
782
783 if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
784 Slog.i(TAG, "Continuing with installation of " + args.packageURI.toString());
785 state.setVerifierResponse(Binder.getCallingUid(), PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
786 try {
787 ret = args.copyApk(mContainerService, true);
788 } catch (RemoteException e) {
789 Slog.e(TAG, "Could not contact the ContainerService");
790 }
791 }
792
Kenny Root5ab21572011-07-27 11:11:19 -0700793 processPendingInstall(args, ret);
794
795 mHandler.sendEmptyMessage(MCS_UNBIND);
796 }
797
798 break;
799 }
800 case PACKAGE_VERIFIED: {
801 final int verificationId = msg.arg1;
Kenny Root5ab21572011-07-27 11:11:19 -0700802
Kenny Root05ca4c92011-09-15 10:36:25 -0700803 final PackageVerificationState state = mPendingVerification.get(verificationId);
804 if (state == null) {
Kenny Roota503a0f2011-10-03 14:45:28 -0700805 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
Kenny Root5ab21572011-07-27 11:11:19 -0700806 break;
807 }
808
Kenny Root05ca4c92011-09-15 10:36:25 -0700809 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
Kenny Root5ab21572011-07-27 11:11:19 -0700810
Kenny Root05ca4c92011-09-15 10:36:25 -0700811 state.setVerifierResponse(response.callerUid, response.code);
812
813 if (state.isVerificationComplete()) {
814 mPendingVerification.remove(verificationId);
815
816 final InstallArgs args = state.getInstallArgs();
817
818 int ret;
819 if (state.isInstallAllowed()) {
820 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
821 try {
822 ret = args.copyApk(mContainerService, true);
823 } catch (RemoteException e) {
824 Slog.e(TAG, "Could not contact the ContainerService");
825 }
826 } else {
827 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
Kenny Root5ab21572011-07-27 11:11:19 -0700828 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700829
830 processPendingInstall(args, ret);
831
832 mHandler.sendEmptyMessage(MCS_UNBIND);
Kenny Root5ab21572011-07-27 11:11:19 -0700833 }
834
Kenny Root5ab21572011-07-27 11:11:19 -0700835 break;
836 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700837 }
838 }
839 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800840
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700841 void scheduleWriteSettingsLocked() {
842 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
843 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
844 }
845 }
Amith Yamasani483f3b02012-03-13 16:08:00 -0700846
847 void scheduleWritePackageRestrictionsLocked(int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -0700848 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700849 mDirtyUsers.add(userId);
850 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
851 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800852 }
853 }
854
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700855 public static final IPackageManager main(Context context, boolean factoryTest,
856 boolean onlyCore) {
857 PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 ServiceManager.addService("package", m);
859 return m;
860 }
861
862 static String[] splitString(String str, char sep) {
863 int count = 1;
864 int i = 0;
865 while ((i=str.indexOf(sep, i)) >= 0) {
866 count++;
867 i++;
868 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 String[] res = new String[count];
871 i=0;
872 count = 0;
873 int lastI=0;
874 while ((i=str.indexOf(sep, i)) >= 0) {
875 res[count] = str.substring(lastI, i);
876 count++;
877 i++;
878 lastI = i;
879 }
880 res[count] = str.substring(lastI, str.length());
881 return res;
882 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800883
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700884 public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800885 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800889 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 mContext = context;
893 mFactoryTest = factoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700894 mOnlyCore = onlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700895 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800896 mMetrics = new DisplayMetrics();
897 mSettings = new Settings();
Kenny Root447106f2011-03-23 11:00:15 -0700898 mSettings.addSharedUserLPw("android.uid.system",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
Dianne Hackborn21fbd1f2012-02-10 10:38:10 -0800900 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
901 mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
902 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903
904 String separateProcesses = SystemProperties.get("debug.separate_processes");
905 if (separateProcesses != null && separateProcesses.length() > 0) {
906 if ("*".equals(separateProcesses)) {
907 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
908 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800909 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 } else {
911 mDefParseFlags = 0;
912 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800913 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 + separateProcesses);
915 }
916 } else {
917 mDefParseFlags = 0;
918 mSeparateProcesses = null;
919 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800920
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700921 mInstaller = new Installer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922
923 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
924 Display d = wm.getDefaultDisplay();
925 d.getMetrics(mMetrics);
926
927 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -0700928 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 synchronized (mPackages) {
930 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700931 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 File dataDir = Environment.getDataDirectory();
934 mAppDataDir = new File(dataDir, "data");
Kenny Root51a573c2012-05-17 13:30:28 -0700935 mAsecInternalPath = new File(dataDir, "app-asec").getPath();
Amith Yamasani0b285492011-04-14 17:35:23 -0700936 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
938
Amith Yamasani13593602012-03-22 16:16:17 -0700939 sUserManager = new UserManager(mInstaller, mUserAppDataDir);
Amith Yamasani0b285492011-04-14 17:35:23 -0700940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 readPermissions();
942
Amith Yamasani483f3b02012-03-13 16:08:00 -0700943 mRestoredSettings = mSettings.readLPw(getUsers());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800945
946 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800948
Suchi Amalapurapudaec1722010-01-14 21:25:16 -0800949 // Set flag to monitor and not change apk file paths when
950 // scanning install directories.
Dianne Hackbornd0c5f512012-06-07 16:53:59 -0700951 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700952 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800953 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800954 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700955 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700960 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800961
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700962 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800963
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700964 /**
965 * Out of paranoia, ensure that everything in the boot class
966 * path has been dexed.
967 */
968 String bootClassPath = System.getProperty("java.boot.class.path");
969 if (bootClassPath != null) {
970 String[] paths = splitString(bootClassPath, ':');
971 for (int i=0; i<paths.length; i++) {
972 try {
973 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
974 libFiles.add(paths[i]);
975 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
976 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700978 } catch (FileNotFoundException e) {
979 Slog.w(TAG, "Boot class path not found: " + paths[i]);
980 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -0700981 Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
982 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 }
984 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700985 } else {
986 Slog.w(TAG, "No BOOTCLASSPATH found!");
987 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800988
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700989 /**
990 * Also ensure all external libraries have had dexopt run on them.
991 */
992 if (mSharedLibraries.size() > 0) {
993 Iterator<String> libs = mSharedLibraries.values().iterator();
994 while (libs.hasNext()) {
995 String lib = libs.next();
996 try {
997 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
998 libFiles.add(lib);
999 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
1000 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001002 } catch (FileNotFoundException e) {
1003 Slog.w(TAG, "Library not found: " + lib);
1004 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -07001005 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
1006 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 }
1008 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001009 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001010
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001011 // Gross hack for now: we know this file doesn't contain any
1012 // code, so don't dexopt it to avoid the resulting log spew.
1013 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
1014
1015 /**
1016 * And there are a number of commands implemented in Java, which
1017 * we currently need to do the dexopt on so that they can be
1018 * run from a non-root shell.
1019 */
1020 String[] frameworkFiles = mFrameworkDir.list();
1021 if (frameworkFiles != null) {
1022 for (int i=0; i<frameworkFiles.length; i++) {
1023 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
1024 String path = libPath.getPath();
1025 // Skip the file if we alrady did it.
1026 if (libFiles.contains(path)) {
1027 continue;
1028 }
1029 // Skip the file if it is not a type we want to dexopt.
1030 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1031 continue;
1032 }
1033 try {
1034 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
1035 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
1036 didDexOpt = true;
1037 }
1038 } catch (FileNotFoundException e) {
1039 Slog.w(TAG, "Jar not found: " + path);
1040 } catch (IOException e) {
1041 Slog.w(TAG, "Exception reading jar: " + path, e);
1042 }
1043 }
1044 }
1045
1046 if (didDexOpt) {
1047 // If we had to do a dexopt of one of the previous
1048 // things, then something on the system has changed.
1049 // Consider this significant, and wipe away all other
1050 // existing dexopt files to ensure we don't leave any
1051 // dangling around.
1052 String[] files = mDalvikCacheDir.list();
1053 if (files != null) {
1054 for (int i=0; i<files.length; i++) {
1055 String fn = files[i];
1056 if (fn.startsWith("data@app@")
1057 || fn.startsWith("data@app-private@")) {
1058 Slog.i(TAG, "Pruning dalvik file: " + fn);
1059 (new File(mDalvikCacheDir, fn)).delete();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001060 }
1061 }
1062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001064
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001065 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 mFrameworkInstallObserver = new AppDirObserver(
1067 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
1068 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001069 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
1070 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001071 scanMode | SCAN_NO_DEX, 0);
Kenny Root51a573c2012-05-17 13:30:28 -07001072
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001073 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
1075 mSystemInstallObserver = new AppDirObserver(
1076 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
1077 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001078 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001079 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Kenny Root208d3412012-05-07 19:42:35 -07001080
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001081 // Collect all vendor packages.
1082 mVendorAppDir = new File("/vendor/app");
1083 mVendorInstallObserver = new AppDirObserver(
1084 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
1085 mVendorInstallObserver.startWatching();
1086 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001087 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001088
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001089 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1090 mInstaller.moveFiles();
1091
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001092 // Prune any system packages that no longer exist.
Kenny Root87b5d7b2012-05-16 13:36:18 -07001093 final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001094 if (!mOnlyCore) {
1095 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1096 while (psit.hasNext()) {
1097 PackageSetting ps = psit.next();
Kenny Root208d3412012-05-07 19:42:35 -07001098
1099 /*
1100 * If this is not a system app, it can't be a
1101 * disable system app.
1102 */
1103 if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
1104 continue;
1105 }
1106
1107 /*
1108 * If the package is scanned, it's not erased.
1109 */
1110 if (mPackages.containsKey(ps.name)) {
1111 /*
1112 * If the system app is both scanned and in the
1113 * disabled packages list, then it must have been
1114 * added via OTA. Remove it from the currently
1115 * scanned package so the previously user-installed
1116 * application can be scanned.
1117 */
1118 if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
1119 mPackages.remove(ps.name);
1120 }
1121
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001122 continue;
1123 }
1124
1125 if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001126 psit.remove();
1127 String msg = "System package " + ps.name
1128 + " no longer exists; wiping its data";
1129 reportSettingsProblem(Log.WARN, msg);
1130 mInstaller.remove(ps.name, 0);
Amith Yamasani13593602012-03-22 16:16:17 -07001131 sUserManager.removePackageForAllUsers(ps.name);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001132 } else {
Kenny Root87b5d7b2012-05-16 13:36:18 -07001133 final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
1134 if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
1135 possiblyDeletedUpdatedSystemApps.add(ps.name);
1136 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001137 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001138 }
1139 }
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 mAppInstallDir = new File(dataDir, "app");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001143 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 //clean up list
1145 for(int i = 0; i < deletePkgsList.size(); i++) {
1146 //clean up here
1147 cleanupInstallFailedPackage(deletePkgsList.get(i));
1148 }
1149 //delete tmp files
1150 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001151
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001152 if (!mOnlyCore) {
1153 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1154 SystemClock.uptimeMillis());
1155 mAppInstallObserver = new AppDirObserver(
1156 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1157 mAppInstallObserver.startWatching();
1158 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1159
1160 mDrmAppInstallObserver = new AppDirObserver(
1161 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1162 mDrmAppInstallObserver.startWatching();
1163 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1164 scanMode, 0);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001165
1166 /**
Kenny Root87b5d7b2012-05-16 13:36:18 -07001167 * Remove disable package settings for any updated system
1168 * apps that were removed via an OTA. If they're not a
1169 * previously-updated app, remove them completely.
1170 * Otherwise, just revoke their system-level permissions.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001171 */
Kenny Root87b5d7b2012-05-16 13:36:18 -07001172 for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001173 PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
Kenny Root87b5d7b2012-05-16 13:36:18 -07001174 mSettings.removeDisabledSystemPackageLPw(deletedAppName);
1175
1176 String msg;
1177 if (deletedPkg == null) {
1178 msg = "Updated system package " + deletedAppName
1179 + " no longer exists; wiping its data";
1180
1181 mInstaller.remove(deletedAppName, 0);
1182 sUserManager.removePackageForAllUsers(deletedAppName);
1183 } else {
1184 msg = "Updated system app + " + deletedAppName
1185 + " no longer present; removing system privileges for "
1186 + deletedAppName;
1187
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001188 deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
1189
1190 PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
1191 deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
1192 }
Kenny Root87b5d7b2012-05-16 13:36:18 -07001193 reportSettingsProblem(Log.WARN, msg);
Kenny Rootc52d6fd2012-05-07 23:04:52 -07001194 }
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001195 } else {
1196 mAppInstallObserver = null;
1197 mDrmAppInstallObserver = null;
1198 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001200 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001202 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1204 + " seconds");
1205
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001206 // If the platform SDK has changed since the last time we booted,
1207 // we need to re-grant app permission to catch any new ones that
1208 // appear. This is really a hack, and means that apps can in some
1209 // cases get permissions that the user didn't initially explicitly
1210 // allow... it would be nice to have some better way to handle
1211 // this situation.
1212 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1213 != mSdkVersion;
1214 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1215 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1216 + "; regranting permissions for internal storage");
1217 mSettings.mInternalSdkPlatform = mSdkVersion;
1218
Dianne Hackborne639da72012-02-21 15:11:13 -08001219 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1220 | (regrantPermissions
1221 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1222 : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223
Dianne Hackborn04505102012-02-29 12:34:04 -08001224 // Verify that all of the preferred activity components actually
1225 // exist. It is possible for applications to be updated and at
1226 // that point remove a previously declared activity component that
1227 // had been set as a preferred activity. We try to clean this up
1228 // the next time we encounter that preferred activity, but it is
1229 // possible for the user flow to never be able to return to that
1230 // situation so here we do a sanity check to make sure we haven't
1231 // left any junk around.
1232 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
1233 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
1234 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
1235 removed.add(pa);
1236 }
1237 }
1238 for (int i=0; i<removed.size(); i++) {
1239 PreferredActivity pa = removed.get(i);
1240 Slog.w(TAG, "Removing dangling preferred activity: "
1241 + pa.mPref.mComponent);
1242 mSettings.mPreferredActivities.removeFilter(pa);
1243 }
1244
Kenny Root447106f2011-03-23 11:00:15 -07001245 // can downgrade to reader
1246 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001248 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 // Now after opening every single application zip, make sure they
1252 // are all flushed. Not really needed, but keeps things nice and
1253 // tidy.
1254 Runtime.getRuntime().gc();
Kenny Root05ca4c92011-09-15 10:36:25 -07001255
1256 mRequiredVerifierPackage = getRequiredVerifierLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 } // synchronized (mPackages)
1258 } // synchronized (mInstallLock)
1259 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001260
Dianne Hackborn58f42a52011-10-10 13:46:34 -07001261 public boolean isFirstBoot() {
1262 return !mRestoredSettings;
1263 }
1264
Kenny Root05ca4c92011-09-15 10:36:25 -07001265 private String getRequiredVerifierLPr() {
1266 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1267 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
Amith Yamasani483f3b02012-03-13 16:08:00 -07001268 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07001269
1270 String requiredVerifier = null;
1271
1272 final int N = receivers.size();
1273 for (int i = 0; i < N; i++) {
1274 final ResolveInfo info = receivers.get(i);
1275
1276 if (info.activityInfo == null) {
1277 continue;
1278 }
1279
1280 final String packageName = info.activityInfo.packageName;
1281
1282 final PackageSetting ps = mSettings.mPackages.get(packageName);
1283 if (ps == null) {
1284 continue;
1285 }
1286
1287 if (!ps.grantedPermissions
1288 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1289 continue;
1290 }
1291
1292 if (requiredVerifier != null) {
1293 throw new RuntimeException("There can be only one required verifier");
1294 }
1295
1296 requiredVerifier = packageName;
1297 }
1298
1299 return requiredVerifier;
1300 }
1301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 @Override
1303 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1304 throws RemoteException {
1305 try {
1306 return super.onTransact(code, data, reply, flags);
1307 } catch (RuntimeException e) {
1308 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001309 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 }
1311 throw e;
1312 }
1313 }
1314
Dianne Hackborne6620b22010-01-22 14:46:21 -08001315 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001316 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001317 int retCode = mInstaller.remove(ps.name, 0);
1318 if (retCode < 0) {
1319 Slog.w(TAG, "Couldn't remove app data directory for package: "
1320 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 } else {
Amith Yamasani13593602012-03-22 16:16:17 -07001322 sUserManager.removePackageForAllUsers(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001324 if (ps.codePath != null) {
1325 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001326 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001327 }
1328 }
1329 if (ps.resourcePath != null) {
1330 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001331 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001332 }
1333 }
Kenny Root447106f2011-03-23 11:00:15 -07001334 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 }
1336
1337 void readPermissions() {
1338 // Read permissions from .../etc/permission directory.
1339 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1340 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001341 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 return;
1343 }
1344 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001345 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 return;
1347 }
1348
1349 // Iterate over the files in the directory and scan .xml files
1350 for (File f : libraryDir.listFiles()) {
1351 // We'll read platform.xml last
1352 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1353 continue;
1354 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001357 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 continue;
1359 }
1360 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001361 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 continue;
1363 }
1364
1365 readPermissionsFromXml(f);
1366 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1369 final File permFile = new File(Environment.getRootDirectory(),
1370 "etc/permissions/platform.xml");
1371 readPermissionsFromXml(permFile);
1372 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001373
1374 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 FileReader permReader = null;
1376 try {
1377 permReader = new FileReader(permFile);
1378 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001379 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 return;
1381 }
1382
1383 try {
1384 XmlPullParser parser = Xml.newPullParser();
1385 parser.setInput(permReader);
1386
1387 XmlUtils.beginDocument(parser, "permissions");
1388
1389 while (true) {
1390 XmlUtils.nextElement(parser);
1391 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1392 break;
1393 }
1394
1395 String name = parser.getName();
1396 if ("group".equals(name)) {
1397 String gidStr = parser.getAttributeValue(null, "gid");
1398 if (gidStr != null) {
1399 int gid = Integer.parseInt(gidStr);
1400 mGlobalGids = appendInt(mGlobalGids, gid);
1401 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001402 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 + parser.getPositionDescription());
1404 }
1405
1406 XmlUtils.skipCurrentTag(parser);
1407 continue;
1408 } else if ("permission".equals(name)) {
1409 String perm = parser.getAttributeValue(null, "name");
1410 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001411 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 + parser.getPositionDescription());
1413 XmlUtils.skipCurrentTag(parser);
1414 continue;
1415 }
1416 perm = perm.intern();
1417 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 } else if ("assign-permission".equals(name)) {
1420 String perm = parser.getAttributeValue(null, "name");
1421 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001422 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 + parser.getPositionDescription());
1424 XmlUtils.skipCurrentTag(parser);
1425 continue;
1426 }
1427 String uidStr = parser.getAttributeValue(null, "uid");
1428 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001429 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 + parser.getPositionDescription());
1431 XmlUtils.skipCurrentTag(parser);
1432 continue;
1433 }
1434 int uid = Process.getUidForName(uidStr);
1435 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001436 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 + uidStr + "\" at "
1438 + parser.getPositionDescription());
1439 XmlUtils.skipCurrentTag(parser);
1440 continue;
1441 }
1442 perm = perm.intern();
1443 HashSet<String> perms = mSystemPermissions.get(uid);
1444 if (perms == null) {
1445 perms = new HashSet<String>();
1446 mSystemPermissions.put(uid, perms);
1447 }
1448 perms.add(perm);
1449 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 } else if ("library".equals(name)) {
1452 String lname = parser.getAttributeValue(null, "name");
1453 String lfile = parser.getAttributeValue(null, "file");
1454 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001455 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 + parser.getPositionDescription());
1457 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001458 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 + parser.getPositionDescription());
1460 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001461 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001462 mSharedLibraries.put(lname, lfile);
1463 }
1464 XmlUtils.skipCurrentTag(parser);
1465 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001466
Dianne Hackborn49237342009-08-27 20:08:01 -07001467 } else if ("feature".equals(name)) {
1468 String fname = parser.getAttributeValue(null, "name");
1469 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001470 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001471 + parser.getPositionDescription());
1472 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001473 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001474 FeatureInfo fi = new FeatureInfo();
1475 fi.name = fname;
1476 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 }
1478 XmlUtils.skipCurrentTag(parser);
1479 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 } else {
1482 XmlUtils.skipCurrentTag(parser);
1483 continue;
1484 }
1485
1486 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001487 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001489 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001491 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 }
1493 }
1494
1495 void readPermission(XmlPullParser parser, String name)
1496 throws IOException, XmlPullParserException {
1497
1498 name = name.intern();
1499
1500 BasePermission bp = mSettings.mPermissions.get(name);
1501 if (bp == null) {
1502 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1503 mSettings.mPermissions.put(name, bp);
1504 }
1505 int outerDepth = parser.getDepth();
1506 int type;
1507 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1508 && (type != XmlPullParser.END_TAG
1509 || parser.getDepth() > outerDepth)) {
1510 if (type == XmlPullParser.END_TAG
1511 || type == XmlPullParser.TEXT) {
1512 continue;
1513 }
1514
1515 String tagName = parser.getName();
1516 if ("group".equals(tagName)) {
1517 String gidStr = parser.getAttributeValue(null, "gid");
1518 if (gidStr != null) {
1519 int gid = Process.getGidForName(gidStr);
1520 bp.gids = appendInt(bp.gids, gid);
1521 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001522 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 + parser.getPositionDescription());
1524 }
1525 }
1526 XmlUtils.skipCurrentTag(parser);
1527 }
1528 }
1529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 static int[] appendInts(int[] cur, int[] add) {
1531 if (add == null) return cur;
1532 if (cur == null) return add;
1533 final int N = add.length;
1534 for (int i=0; i<N; i++) {
1535 cur = appendInt(cur, add[i]);
1536 }
1537 return cur;
1538 }
1539
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001540 static int[] removeInts(int[] cur, int[] rem) {
1541 if (rem == null) return cur;
1542 if (cur == null) return cur;
1543 final int N = rem.length;
1544 for (int i=0; i<N; i++) {
1545 cur = removeInt(cur, rem[i]);
1546 }
1547 return cur;
1548 }
1549
Amith Yamasani13593602012-03-22 16:16:17 -07001550 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1551 if (!sUserManager.exists(userId)) return null;
1552 PackageInfo pi;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001553 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1554 // The package has been uninstalled but has retained data and resources.
Amith Yamasani13593602012-03-22 16:16:17 -07001555 pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
1556 } else {
1557 final PackageSetting ps = (PackageSetting) p.mExtras;
1558 if (ps == null) {
1559 return null;
1560 }
1561 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1562 pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
1563 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1564 ps.getStopped(userId), ps.getEnabled(userId), userId);
1565 pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
1566 pi.applicationInfo.enabled =
1567 pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
1568 || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001569 }
Amith Yamasani13593602012-03-22 16:16:17 -07001570 return pi;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 }
1572
Amith Yamasani483f3b02012-03-13 16:08:00 -07001573 @Override
1574 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001575 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001576 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 synchronized (mPackages) {
1578 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001579 if (DEBUG_PACKAGE_INFO)
1580 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001582 return generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 }
1584 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001585 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 }
1587 }
1588 return null;
1589 }
1590
Dianne Hackborn47096932010-02-11 15:57:09 -08001591 public String[] currentToCanonicalPackageNames(String[] names) {
1592 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001593 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001594 synchronized (mPackages) {
1595 for (int i=names.length-1; i>=0; i--) {
1596 PackageSetting ps = mSettings.mPackages.get(names[i]);
1597 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1598 }
1599 }
1600 return out;
1601 }
1602
1603 public String[] canonicalToCurrentPackageNames(String[] names) {
1604 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001605 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001606 synchronized (mPackages) {
1607 for (int i=names.length-1; i>=0; i--) {
1608 String cur = mSettings.mRenamedPackages.get(names[i]);
1609 out[i] = cur != null ? cur : names[i];
1610 }
1611 }
1612 return out;
1613 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001614
1615 @Override
1616 public int getPackageUid(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001617 if (!sUserManager.exists(userId)) return -1;
Kenny Root447106f2011-03-23 11:00:15 -07001618 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 synchronized (mPackages) {
1620 PackageParser.Package p = mPackages.get(packageName);
1621 if(p != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001622 return UserId.getUid(userId, p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 }
1624 PackageSetting ps = mSettings.mPackages.get(packageName);
1625 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1626 return -1;
1627 }
1628 p = ps.pkg;
Amith Yamasani483f3b02012-03-13 16:08:00 -07001629 return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 }
1631 }
1632
1633 public int[] getPackageGids(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001634 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 synchronized (mPackages) {
1636 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001637 if (DEBUG_PACKAGE_INFO)
1638 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 if (p != null) {
1640 final PackageSetting ps = (PackageSetting)p.mExtras;
1641 final SharedUserSetting suid = ps.sharedUser;
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07001642 int[] gids = suid != null ? suid.gids : ps.gids;
1643
1644 // include GIDs for any unenforced permissions
1645 if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
1646 final BasePermission basePerm = mSettings.mPermissions.get(
1647 READ_EXTERNAL_STORAGE);
1648 gids = appendInts(gids, basePerm.gids);
1649 }
1650
1651 return gids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
1653 }
1654 // stupid thing to indicate an error.
1655 return new int[0];
1656 }
1657
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001658 static final PermissionInfo generatePermissionInfo(
1659 BasePermission bp, int flags) {
1660 if (bp.perm != null) {
1661 return PackageParser.generatePermissionInfo(bp.perm, flags);
1662 }
1663 PermissionInfo pi = new PermissionInfo();
1664 pi.name = bp.name;
1665 pi.packageName = bp.sourcePackage;
1666 pi.nonLocalizedLabel = bp.name;
1667 pi.protectionLevel = bp.protectionLevel;
1668 return pi;
1669 }
1670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001672 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 synchronized (mPackages) {
1674 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001675 if (p != null) {
1676 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 }
1678 return null;
1679 }
1680 }
1681
1682 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001683 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 synchronized (mPackages) {
1685 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1686 for (BasePermission p : mSettings.mPermissions.values()) {
1687 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001688 if (p.perm == null || p.perm.info.group == null) {
1689 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 }
1691 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001692 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1694 }
1695 }
1696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 if (out.size() > 0) {
1699 return out;
1700 }
1701 return mPermissionGroups.containsKey(group) ? out : null;
1702 }
1703 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001706 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 synchronized (mPackages) {
1708 return PackageParser.generatePermissionGroupInfo(
1709 mPermissionGroups.get(name), flags);
1710 }
1711 }
1712
1713 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001714 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 synchronized (mPackages) {
1716 final int N = mPermissionGroups.size();
1717 ArrayList<PermissionGroupInfo> out
1718 = new ArrayList<PermissionGroupInfo>(N);
1719 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1720 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1721 }
1722 return out;
1723 }
1724 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001725
Amith Yamasani483f3b02012-03-13 16:08:00 -07001726 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
1727 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001728 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001730 if (ps != null) {
1731 if (ps.pkg == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001732 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
Kenny Root447106f2011-03-23 11:00:15 -07001733 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 return pInfo.applicationInfo;
1735 }
1736 return null;
1737 }
Amith Yamasani13593602012-03-22 16:16:17 -07001738 return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
1739 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 }
1741 return null;
1742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001743
Amith Yamasani483f3b02012-03-13 16:08:00 -07001744 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
1745 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001746 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001748 if (ps != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001749 PackageParser.Package pkg = new PackageParser.Package(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001750 if (ps.pkg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 ps.pkg = new PackageParser.Package(packageName);
1752 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001753 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1754 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1755 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
Amith Yamasani0b285492011-04-14 17:35:23 -07001756 ps.pkg.applicationInfo.dataDir =
1757 getDataPathForPackage(ps.pkg.packageName, 0).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001758 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 }
Amith Yamasani13593602012-03-22 16:16:17 -07001760 // ps.pkg.mSetEnabled = ps.getEnabled(userId);
1761 // ps.pkg.mSetStopped = ps.getStopped(userId);
1762 return generatePackageInfo(ps.pkg, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 }
1764 return null;
1765 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001766
Amith Yamasani483f3b02012-03-13 16:08:00 -07001767 @Override
1768 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001769 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001770 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 synchronized (mPackages) {
1772 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001773 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 TAG, "getApplicationInfo " + packageName
1775 + ": " + p);
1776 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001777 PackageSetting ps = mSettings.mPackages.get(packageName);
1778 if (ps == null) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 // Note: isEnabledLP() does not apply here - always return info
Amith Yamasani13593602012-03-22 16:16:17 -07001780 return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
1781 ps.getEnabled(userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
1783 if ("android".equals(packageName)||"system".equals(packageName)) {
1784 return mAndroidApplication;
1785 }
1786 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001787 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 }
1789 }
1790 return null;
1791 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001792
1793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1795 mContext.enforceCallingOrSelfPermission(
1796 android.Manifest.permission.CLEAR_APP_CACHE, null);
1797 // Queue up an async operation since clearing cache may take a little while.
1798 mHandler.post(new Runnable() {
1799 public void run() {
1800 mHandler.removeCallbacks(this);
1801 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001802 retCode = mInstaller.freeCache(freeStorageSize);
1803 if (retCode < 0) {
1804 Slog.w(TAG, "Couldn't clear application caches");
1805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 if (observer != null) {
1807 try {
1808 observer.onRemoveCompleted(null, (retCode >= 0));
1809 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001810 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 }
1812 }
1813 }
1814 });
1815 }
1816
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001817 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001818 mContext.enforceCallingOrSelfPermission(
1819 android.Manifest.permission.CLEAR_APP_CACHE, null);
1820 // Queue up an async operation since clearing cache may take a little while.
1821 mHandler.post(new Runnable() {
1822 public void run() {
1823 mHandler.removeCallbacks(this);
1824 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001825 retCode = mInstaller.freeCache(freeStorageSize);
1826 if (retCode < 0) {
1827 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001828 }
1829 if(pi != null) {
1830 try {
1831 // Callback via pending intent
1832 int code = (retCode >= 0) ? 1 : 0;
1833 pi.sendIntent(null, code, null,
1834 null, null);
1835 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001836 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001837 }
1838 }
1839 }
1840 });
1841 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001842
Amith Yamasani483f3b02012-03-13 16:08:00 -07001843 @Override
1844 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001845 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 synchronized (mPackages) {
1847 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001848
Kenny Root9718cf52011-02-23 16:45:26 -08001849 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001850 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001851 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1852 if (ps == null) return null;
1853 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1854 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 }
1856 if (mResolveComponentName.equals(component)) {
1857 return mResolveActivity;
1858 }
1859 }
1860 return null;
1861 }
1862
Amith Yamasani483f3b02012-03-13 16:08:00 -07001863 @Override
1864 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001865 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 synchronized (mPackages) {
1867 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001868 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 TAG, "getReceiverInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001870 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001871 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1872 if (ps == null) return null;
1873 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1874 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 }
1876 }
1877 return null;
1878 }
1879
Amith Yamasani483f3b02012-03-13 16:08:00 -07001880 @Override
1881 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001882 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 synchronized (mPackages) {
1884 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001885 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 TAG, "getServiceInfo " + component + ": " + s);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001887 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001888 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1889 if (ps == null) return null;
1890 return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
1891 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
1893 }
1894 return null;
1895 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001896
Amith Yamasani483f3b02012-03-13 16:08:00 -07001897 @Override
1898 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001899 if (!sUserManager.exists(userId)) return null;
Dianne Hackborn361199b2010-08-30 17:42:07 -07001900 synchronized (mPackages) {
1901 PackageParser.Provider p = mProvidersByComponent.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001902 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07001903 TAG, "getProviderInfo " + component + ": " + p);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001904 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001905 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1906 if (ps == null) return null;
1907 return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
1908 ps.getEnabled(userId), userId);
Dianne Hackborn361199b2010-08-30 17:42:07 -07001909 }
1910 }
1911 return null;
1912 }
1913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 public String[] getSystemSharedLibraryNames() {
1915 Set<String> libSet;
1916 synchronized (mPackages) {
1917 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001918 int size = libSet.size();
1919 if (size > 0) {
1920 String[] libs = new String[size];
1921 libSet.toArray(libs);
1922 return libs;
1923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001925 return null;
1926 }
1927
1928 public FeatureInfo[] getSystemAvailableFeatures() {
1929 Collection<FeatureInfo> featSet;
1930 synchronized (mPackages) {
1931 featSet = mAvailableFeatures.values();
1932 int size = featSet.size();
1933 if (size > 0) {
1934 FeatureInfo[] features = new FeatureInfo[size+1];
1935 featSet.toArray(features);
1936 FeatureInfo fi = new FeatureInfo();
1937 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1938 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1939 features[size] = fi;
1940 return features;
1941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 }
1943 return null;
1944 }
1945
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001946 public boolean hasSystemFeature(String name) {
1947 synchronized (mPackages) {
1948 return mAvailableFeatures.containsKey(name);
1949 }
1950 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001951
Amith Yamasani483f3b02012-03-13 16:08:00 -07001952 private void checkValidCaller(int uid, int userId) {
1953 if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
1954 return;
1955
1956 throw new SecurityException("Caller uid=" + uid
1957 + " is not privileged to communicate with user=" + userId);
1958 }
1959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 public int checkPermission(String permName, String pkgName) {
1961 synchronized (mPackages) {
1962 PackageParser.Package p = mPackages.get(pkgName);
1963 if (p != null && p.mExtras != null) {
1964 PackageSetting ps = (PackageSetting)p.mExtras;
1965 if (ps.sharedUser != null) {
1966 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1967 return PackageManager.PERMISSION_GRANTED;
1968 }
1969 } else if (ps.grantedPermissions.contains(permName)) {
1970 return PackageManager.PERMISSION_GRANTED;
1971 }
1972 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07001973 if (!isPermissionEnforcedLocked(permName)) {
1974 return PackageManager.PERMISSION_GRANTED;
1975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 }
1977 return PackageManager.PERMISSION_DENIED;
1978 }
1979
1980 public int checkUidPermission(String permName, int uid) {
1981 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07001982 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001984 GrantedPermissions gp = (GrantedPermissions)obj;
1985 if (gp.grantedPermissions.contains(permName)) {
1986 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001987 }
1988 } else {
1989 HashSet<String> perms = mSystemPermissions.get(uid);
1990 if (perms != null && perms.contains(permName)) {
1991 return PackageManager.PERMISSION_GRANTED;
1992 }
1993 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07001994 if (!isPermissionEnforcedLocked(permName)) {
1995 return PackageManager.PERMISSION_GRANTED;
1996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 }
1998 return PackageManager.PERMISSION_DENIED;
1999 }
2000
2001 private BasePermission findPermissionTreeLP(String permName) {
2002 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
2003 if (permName.startsWith(bp.name) &&
2004 permName.length() > bp.name.length() &&
2005 permName.charAt(bp.name.length()) == '.') {
2006 return bp;
2007 }
2008 }
2009 return null;
2010 }
2011
2012 private BasePermission checkPermissionTreeLP(String permName) {
2013 if (permName != null) {
2014 BasePermission bp = findPermissionTreeLP(permName);
2015 if (bp != null) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002016 if (bp.uid == UserId.getAppId(Binder.getCallingUid())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 return bp;
2018 }
2019 throw new SecurityException("Calling uid "
2020 + Binder.getCallingUid()
2021 + " is not allowed to add to permission tree "
2022 + bp.name + " owned by uid " + bp.uid);
2023 }
2024 }
2025 throw new SecurityException("No permission tree found for " + permName);
2026 }
2027
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002028 static boolean compareStrings(CharSequence s1, CharSequence s2) {
2029 if (s1 == null) {
2030 return s2 == null;
2031 }
2032 if (s2 == null) {
2033 return false;
2034 }
2035 if (s1.getClass() != s2.getClass()) {
2036 return false;
2037 }
2038 return s1.equals(s2);
2039 }
2040
2041 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
2042 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07002043 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002044 if (pi1.protectionLevel != pi2.protectionLevel) return false;
2045 if (!compareStrings(pi1.name, pi2.name)) return false;
2046 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
2047 // We'll take care of setting this one.
2048 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
2049 // These are not currently stored in settings.
2050 //if (!compareStrings(pi1.group, pi2.group)) return false;
2051 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
2052 //if (pi1.labelRes != pi2.labelRes) return false;
2053 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
2054 return true;
2055 }
2056
2057 boolean addPermissionLocked(PermissionInfo info, boolean async) {
2058 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
2059 throw new SecurityException("Label must be specified in permission");
2060 }
2061 BasePermission tree = checkPermissionTreeLP(info.name);
2062 BasePermission bp = mSettings.mPermissions.get(info.name);
2063 boolean added = bp == null;
2064 boolean changed = true;
Dianne Hackborne639da72012-02-21 15:11:13 -08002065 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002066 if (added) {
2067 bp = new BasePermission(info.name, tree.sourcePackage,
2068 BasePermission.TYPE_DYNAMIC);
2069 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
2070 throw new SecurityException(
2071 "Not allowed to modify non-dynamic permission "
2072 + info.name);
2073 } else {
Dianne Hackborne639da72012-02-21 15:11:13 -08002074 if (bp.protectionLevel == fixedLevel
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002075 && bp.perm.owner.equals(tree.perm.owner)
2076 && bp.uid == tree.uid
2077 && comparePermissionInfos(bp.perm.info, info)) {
2078 changed = false;
2079 }
2080 }
Dianne Hackborne639da72012-02-21 15:11:13 -08002081 bp.protectionLevel = fixedLevel;
2082 info = new PermissionInfo(info);
2083 info.protectionLevel = fixedLevel;
2084 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002085 bp.perm.info.packageName = tree.perm.info.packageName;
2086 bp.uid = tree.uid;
2087 if (added) {
2088 mSettings.mPermissions.put(info.name, bp);
2089 }
2090 if (changed) {
2091 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07002092 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002093 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002094 scheduleWriteSettingsLocked();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002095 }
2096 }
2097 return added;
2098 }
2099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002100 public boolean addPermission(PermissionInfo info) {
2101 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002102 return addPermissionLocked(info, false);
2103 }
2104 }
2105
2106 public boolean addPermissionAsync(PermissionInfo info) {
2107 synchronized (mPackages) {
2108 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 }
2110 }
2111
2112 public void removePermission(String name) {
2113 synchronized (mPackages) {
2114 checkPermissionTreeLP(name);
2115 BasePermission bp = mSettings.mPermissions.get(name);
2116 if (bp != null) {
2117 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2118 throw new SecurityException(
2119 "Not allowed to modify non-dynamic permission "
2120 + name);
2121 }
2122 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07002123 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 }
2125 }
2126 }
2127
Dianne Hackborne639da72012-02-21 15:11:13 -08002128 public void grantPermission(String packageName, String permissionName) {
2129 mContext.enforceCallingOrSelfPermission(
2130 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2131 synchronized (mPackages) {
2132 final PackageParser.Package pkg = mPackages.get(packageName);
2133 if (pkg == null) {
2134 throw new IllegalArgumentException("Unknown package: " + packageName);
2135 }
2136 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2137 if (bp == null) {
2138 throw new IllegalArgumentException("Unknown permission: " + packageName);
2139 }
2140 if (!pkg.requestedPermissions.contains(permissionName)) {
2141 throw new SecurityException("Package " + packageName
2142 + " has not requested permission " + permissionName);
2143 }
2144 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2145 throw new SecurityException("Permission " + permissionName
2146 + " is not a development permission");
2147 }
2148 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2149 if (ps == null) {
2150 return;
2151 }
2152 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2153 if (gp.grantedPermissions.add(permissionName)) {
2154 if (ps.haveGids) {
2155 gp.gids = appendInts(gp.gids, bp.gids);
2156 }
2157 mSettings.writeLPr();
2158 }
2159 }
2160 }
2161
2162 public void revokePermission(String packageName, String permissionName) {
2163 synchronized (mPackages) {
2164 final PackageParser.Package pkg = mPackages.get(packageName);
2165 if (pkg == null) {
2166 throw new IllegalArgumentException("Unknown package: " + packageName);
2167 }
2168 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2169 mContext.enforceCallingOrSelfPermission(
2170 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2171 }
2172 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2173 if (bp == null) {
2174 throw new IllegalArgumentException("Unknown permission: " + packageName);
2175 }
2176 if (!pkg.requestedPermissions.contains(permissionName)) {
2177 throw new SecurityException("Package " + packageName
2178 + " has not requested permission " + permissionName);
2179 }
2180 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2181 throw new SecurityException("Permission " + permissionName
2182 + " is not a development permission");
2183 }
2184 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2185 if (ps == null) {
2186 return;
2187 }
2188 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2189 if (gp.grantedPermissions.remove(permissionName)) {
2190 gp.grantedPermissions.remove(permissionName);
2191 if (ps.haveGids) {
2192 gp.gids = removeInts(gp.gids, bp.gids);
2193 }
2194 mSettings.writeLPr();
2195 }
2196 }
2197 }
2198
Dianne Hackborn854060af2009-07-09 18:14:31 -07002199 public boolean isProtectedBroadcast(String actionName) {
2200 synchronized (mPackages) {
2201 return mProtectedBroadcasts.contains(actionName);
2202 }
2203 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205 public int checkSignatures(String pkg1, String pkg2) {
2206 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002207 final PackageParser.Package p1 = mPackages.get(pkg1);
2208 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 if (p1 == null || p1.mExtras == null
2210 || p2 == null || p2.mExtras == null) {
2211 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2212 }
Kenny Root447106f2011-03-23 11:00:15 -07002213 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 }
2215 }
2216
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002217 public int checkUidSignatures(int uid1, int uid2) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002218 // Map to base uids.
2219 uid1 = UserId.getAppId(uid1);
2220 uid2 = UserId.getAppId(uid2);
Kenny Root447106f2011-03-23 11:00:15 -07002221 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002222 synchronized (mPackages) {
2223 Signature[] s1;
2224 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07002225 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002226 if (obj != null) {
2227 if (obj instanceof SharedUserSetting) {
2228 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2229 } else if (obj instanceof PackageSetting) {
2230 s1 = ((PackageSetting)obj).signatures.mSignatures;
2231 } else {
2232 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2233 }
2234 } else {
2235 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2236 }
Kenny Root447106f2011-03-23 11:00:15 -07002237 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002238 if (obj != null) {
2239 if (obj instanceof SharedUserSetting) {
2240 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2241 } else if (obj instanceof PackageSetting) {
2242 s2 = ((PackageSetting)obj).signatures.mSignatures;
2243 } else {
2244 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2245 }
2246 } else {
2247 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2248 }
Kenny Root447106f2011-03-23 11:00:15 -07002249 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002250 }
2251 }
2252
Kenny Root447106f2011-03-23 11:00:15 -07002253 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002254 if (s1 == null) {
2255 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2257 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2258 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002259 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2261 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002262 HashSet<Signature> set1 = new HashSet<Signature>();
2263 for (Signature sig : s1) {
2264 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002266 HashSet<Signature> set2 = new HashSet<Signature>();
2267 for (Signature sig : s2) {
2268 set2.add(sig);
2269 }
2270 // Make sure s2 contains all signatures in s1.
2271 if (set1.equals(set2)) {
2272 return PackageManager.SIGNATURE_MATCH;
2273 }
2274 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
2276
2277 public String[] getPackagesForUid(int uid) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002278 uid = UserId.getAppId(uid);
Kenny Root447106f2011-03-23 11:00:15 -07002279 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002281 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002283 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07002285 final String[] res = new String[N];
2286 final Iterator<PackageSetting> it = sus.packages.iterator();
2287 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002288 while (it.hasNext()) {
2289 res[i++] = it.next().name;
2290 }
2291 return res;
2292 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002293 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002294 return new String[] { ps.name };
2295 }
2296 }
2297 return null;
2298 }
2299
2300 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07002301 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002303 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002305 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306 return sus.name + ":" + sus.userId;
2307 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002308 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 return ps.name;
2310 }
2311 }
2312 return null;
2313 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 public int getUidForSharedUser(String sharedUserName) {
2316 if(sharedUserName == null) {
2317 return -1;
2318 }
Kenny Root447106f2011-03-23 11:00:15 -07002319 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002321 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
Amith Yamasani742a6712011-05-04 14:49:28 -07002322 if (suid == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 return -1;
2324 }
2325 return suid.userId;
2326 }
2327 }
2328
Amith Yamasani483f3b02012-03-13 16:08:00 -07002329 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002331 int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002332 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002333 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2334 return chooseBestActivity(intent, resolvedType, flags, query, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02002335 }
2336
Mihai Predaeae850c2009-05-13 10:13:48 +02002337 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002338 int flags, List<ResolveInfo> query, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 if (query != null) {
2340 final int N = query.size();
2341 if (N == 1) {
2342 return query.get(0);
2343 } else if (N > 1) {
2344 // If there is more than one activity with the same priority,
2345 // then let the user decide between them.
2346 ResolveInfo r0 = query.get(0);
2347 ResolveInfo r1 = query.get(1);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002348 if (DEBUG_INTENT_MATCHING) {
2349 Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
2350 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 }
2352 // If the first activity has a higher priority, or a different
2353 // default, then it is always desireable to pick it.
2354 if (r0.priority != r1.priority
2355 || r0.preferredOrder != r1.preferredOrder
2356 || r0.isDefault != r1.isDefault) {
2357 return query.get(0);
2358 }
2359 // If we have saved a preference for a preferred activity for
2360 // this Intent, use that.
2361 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002362 flags, query, r0.priority, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 if (ri != null) {
2364 return ri;
2365 }
2366 return mResolveInfo;
2367 }
2368 }
2369 return null;
2370 }
2371
2372 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002373 int flags, List<ResolveInfo> query, int priority, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002374 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002375 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 synchronized (mPackages) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002377 if (intent.getSelector() != null) {
2378 intent = intent.getSelector();
2379 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2381 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002382 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002383 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 if (prefs != null && prefs.size() > 0) {
2385 // First figure out how good the original match set is.
2386 // We will only allow preferred activities that came
2387 // from the same match quality.
2388 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002389
2390 if (DEBUG_PREFERRED) {
2391 Log.v(TAG, "Figuring out best match...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 }
Kenny Root447106f2011-03-23 11:00:15 -07002393
2394 final int N = query.size();
2395 for (int j=0; j<N; j++) {
2396 final ResolveInfo ri = query.get(j);
2397 if (DEBUG_PREFERRED) {
2398 Log.v(TAG, "Match for " + ri.activityInfo + ": 0x"
2399 + Integer.toHexString(match));
2400 }
2401 if (ri.match > match) {
2402 match = ri.match;
2403 }
2404 }
2405
2406 if (DEBUG_PREFERRED) {
2407 Log.v(TAG, "Best match: 0x" + Integer.toHexString(match));
2408 }
2409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 match &= IntentFilter.MATCH_CATEGORY_MASK;
2411 final int M = prefs.size();
2412 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002413 final PreferredActivity pa = prefs.get(i);
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002414 if (pa.mPref.mMatch != match) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 continue;
2416 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07002417 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 if (DEBUG_PREFERRED) {
2419 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002420 if (ai != null) {
2421 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2422 } else {
2423 Log.v(TAG, " null");
2424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002426 if (ai == null) {
2427 // This previously registered preferred activity
2428 // component is no longer known. Most likely an update
2429 // to the app was installed and in the new version this
2430 // component no longer exists. Clean it up by removing
2431 // it from the preferred activities list, and skip it.
2432 Slog.w(TAG, "Removing dangling preferred activity: "
2433 + pa.mPref.mComponent);
2434 mSettings.mPreferredActivities.removeFilter(pa);
2435 continue;
2436 }
2437 for (int j=0; j<N; j++) {
2438 final ResolveInfo ri = query.get(j);
2439 if (!ri.activityInfo.applicationInfo.packageName
2440 .equals(ai.applicationInfo.packageName)) {
2441 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002443 if (!ri.activityInfo.name.equals(ai.name)) {
2444 continue;
2445 }
2446
2447 // Okay we found a previously set preferred app.
2448 // If the result set is different from when this
2449 // was created, we need to clear it and re-ask the
2450 // user their preference.
2451 if (!pa.mPref.sameSet(query, priority)) {
2452 Slog.i(TAG, "Result set changed, dropping preferred activity for "
2453 + intent + " type " + resolvedType);
2454 mSettings.mPreferredActivities.removeFilter(pa);
2455 return null;
2456 }
2457
2458 // Yay!
2459 return ri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 }
2461 }
2462 }
2463 }
2464 return null;
2465 }
2466
Amith Yamasani483f3b02012-03-13 16:08:00 -07002467 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 public List<ResolveInfo> queryIntentActivities(Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002469 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002470 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002471 ComponentName comp = intent.getComponent();
2472 if (comp == null) {
2473 if (intent.getSelector() != null) {
2474 intent = intent.getSelector();
2475 comp = intent.getComponent();
2476 }
2477 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002480 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002481 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002483 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 ri.activityInfo = ai;
2485 list.add(ri);
2486 }
2487 return list;
2488 }
2489
Kenny Root447106f2011-03-23 11:00:15 -07002490 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002492 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002493 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002494 return mActivities.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002495 }
Kenny Root447106f2011-03-23 11:00:15 -07002496 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002497 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002498 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002499 pkg.activities, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002500 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002501 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
2503 }
2504
Amith Yamasani483f3b02012-03-13 16:08:00 -07002505 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2507 Intent[] specifics, String[] specificTypes, Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002508 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002509 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 final String resultsAction = intent.getAction();
2511
Kenny Root447106f2011-03-23 11:00:15 -07002512 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
Amith Yamasani483f3b02012-03-13 16:08:00 -07002513 | PackageManager.GET_RESOLVED_FILTER, userId);
Kenny Root447106f2011-03-23 11:00:15 -07002514
2515 if (DEBUG_INTENT_MATCHING) {
2516 Log.v(TAG, "Query " + intent + ": " + results);
2517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518
2519 int specificsPos = 0;
2520 int N;
2521
2522 // todo: note that the algorithm used here is O(N^2). This
2523 // isn't a problem in our current environment, but if we start running
2524 // into situations where we have more than 5 or 10 matches then this
2525 // should probably be changed to something smarter...
2526
2527 // First we go through and resolve each of the specific items
2528 // that were supplied, taking care of removing any corresponding
2529 // duplicate items in the generic resolve list.
2530 if (specifics != null) {
2531 for (int i=0; i<specifics.length; i++) {
2532 final Intent sintent = specifics[i];
2533 if (sintent == null) {
2534 continue;
2535 }
2536
Kenny Root447106f2011-03-23 11:00:15 -07002537 if (DEBUG_INTENT_MATCHING) {
2538 Log.v(TAG, "Specific #" + i + ": " + sintent);
2539 }
2540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 String action = sintent.getAction();
2542 if (resultsAction != null && resultsAction.equals(action)) {
2543 // If this action was explicitly requested, then don't
2544 // remove things that have it.
2545 action = null;
2546 }
Kenny Root447106f2011-03-23 11:00:15 -07002547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002548 ResolveInfo ri = null;
2549 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002550
2551 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 if (comp == null) {
2553 ri = resolveIntent(
2554 sintent,
2555 specificTypes != null ? specificTypes[i] : null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002556 flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 if (ri == null) {
2558 continue;
2559 }
2560 if (ri == mResolveInfo) {
2561 // ACK! Must do something better with this.
2562 }
2563 ai = ri.activityInfo;
2564 comp = new ComponentName(ai.applicationInfo.packageName,
2565 ai.name);
2566 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002567 ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 if (ai == null) {
2569 continue;
2570 }
2571 }
2572
2573 // Look for any generic query activities that are duplicates
2574 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002575 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002576 N = results.size();
2577 int j;
2578 for (j=specificsPos; j<N; j++) {
2579 ResolveInfo sri = results.get(j);
2580 if ((sri.activityInfo.name.equals(comp.getClassName())
2581 && sri.activityInfo.applicationInfo.packageName.equals(
2582 comp.getPackageName()))
2583 || (action != null && sri.filter.matchAction(action))) {
2584 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002585 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 TAG, "Removing duplicate item from " + j
2587 + " due to specific " + specificsPos);
2588 if (ri == null) {
2589 ri = sri;
2590 }
2591 j--;
2592 N--;
2593 }
2594 }
2595
2596 // Add this specific item to its proper place.
2597 if (ri == null) {
2598 ri = new ResolveInfo();
2599 ri.activityInfo = ai;
2600 }
2601 results.add(specificsPos, ri);
2602 ri.specificIndex = i;
2603 specificsPos++;
2604 }
2605 }
2606
2607 // Now we go through the remaining generic results and remove any
2608 // duplicate actions that are found here.
2609 N = results.size();
2610 for (int i=specificsPos; i<N-1; i++) {
2611 final ResolveInfo rii = results.get(i);
2612 if (rii.filter == null) {
2613 continue;
2614 }
2615
2616 // Iterate over all of the actions of this result's intent
2617 // filter... typically this should be just one.
2618 final Iterator<String> it = rii.filter.actionsIterator();
2619 if (it == null) {
2620 continue;
2621 }
2622 while (it.hasNext()) {
2623 final String action = it.next();
2624 if (resultsAction != null && resultsAction.equals(action)) {
2625 // If this action was explicitly requested, then don't
2626 // remove things that have it.
2627 continue;
2628 }
2629 for (int j=i+1; j<N; j++) {
2630 final ResolveInfo rij = results.get(j);
2631 if (rij.filter != null && rij.filter.hasAction(action)) {
2632 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002633 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 TAG, "Removing duplicate item from " + j
2635 + " due to action " + action + " at " + i);
2636 j--;
2637 N--;
2638 }
2639 }
2640 }
2641
2642 // If the caller didn't request filter information, drop it now
2643 // so we don't have to marshall/unmarshall it.
2644 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2645 rii.filter = null;
2646 }
2647 }
2648
2649 // Filter out the caller activity if so requested.
2650 if (caller != null) {
2651 N = results.size();
2652 for (int i=0; i<N; i++) {
2653 ActivityInfo ainfo = results.get(i).activityInfo;
2654 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2655 && caller.getClassName().equals(ainfo.name)) {
2656 results.remove(i);
2657 break;
2658 }
2659 }
2660 }
2661
2662 // If the caller didn't request filter information,
2663 // drop them now so we don't have to
2664 // marshall/unmarshall it.
2665 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2666 N = results.size();
2667 for (int i=0; i<N; i++) {
2668 results.get(i).filter = null;
2669 }
2670 }
2671
Kenny Root9718cf52011-02-23 16:45:26 -08002672 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 return results;
2674 }
2675
Amith Yamasani483f3b02012-03-13 16:08:00 -07002676 @Override
2677 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
2678 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002679 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002680 ComponentName comp = intent.getComponent();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002681 if (comp == null) {
2682 if (intent.getSelector() != null) {
2683 intent = intent.getSelector();
2684 comp = intent.getComponent();
2685 }
2686 }
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002687 if (comp != null) {
2688 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002689 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002690 if (ai != null) {
2691 ResolveInfo ri = new ResolveInfo();
2692 ri.activityInfo = ai;
2693 list.add(ri);
2694 }
2695 return list;
2696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002697
Kenny Root447106f2011-03-23 11:00:15 -07002698 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002700 String pkgName = intent.getPackage();
2701 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002702 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002703 }
Kenny Root447106f2011-03-23 11:00:15 -07002704 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002705 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002706 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
2707 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002708 }
2709 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 }
2711 }
2712
Amith Yamasani483f3b02012-03-13 16:08:00 -07002713 @Override
2714 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
2715 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07002716 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 if (query != null) {
2718 if (query.size() >= 1) {
2719 // If there is more than one service with the same priority,
2720 // just arbitrarily pick the first one.
2721 return query.get(0);
2722 }
2723 }
2724 return null;
2725 }
2726
Amith Yamasani483f3b02012-03-13 16:08:00 -07002727 @Override
2728 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
2729 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002730 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002731 ComponentName comp = intent.getComponent();
2732 if (comp == null) {
2733 if (intent.getSelector() != null) {
2734 intent = intent.getSelector();
2735 comp = intent.getComponent();
2736 }
2737 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002739 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002740 final ServiceInfo si = getServiceInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002742 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002743 ri.serviceInfo = si;
2744 list.add(ri);
2745 }
2746 return list;
2747 }
2748
Kenny Root447106f2011-03-23 11:00:15 -07002749 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002751 String pkgName = intent.getPackage();
2752 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002753 return mServices.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002754 }
Kenny Root447106f2011-03-23 11:00:15 -07002755 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002756 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002757 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
2758 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002759 }
2760 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
2762 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002763
Kenny Root0e2c0f32011-04-15 17:50:10 -07002764 private static final int getContinuationPoint(final String[] keys, final String key) {
2765 final int index;
2766 if (key == null) {
2767 index = 0;
2768 } else {
2769 final int insertPoint = Arrays.binarySearch(keys, key);
2770 if (insertPoint < 0) {
2771 index = -insertPoint;
2772 } else {
2773 index = insertPoint + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 }
2775 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002776 return index;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002777 }
2778
Kenny Root0e2c0f32011-04-15 17:50:10 -07002779 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
2780 final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
2781 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2782 final String[] keys;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002783 int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784
Kenny Root447106f2011-03-23 11:00:15 -07002785 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 synchronized (mPackages) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002787 if (listUninstalled) {
2788 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2789 } else {
2790 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2791 }
2792
2793 Arrays.sort(keys);
2794 int i = getContinuationPoint(keys, lastRead);
2795 final int N = keys.length;
2796
2797 while (i < N) {
2798 final String packageName = keys[i++];
2799
2800 PackageInfo pi = null;
2801 if (listUninstalled) {
2802 final PackageSetting ps = mSettings.mPackages.get(packageName);
2803 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002804 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002806 } else {
2807 final PackageParser.Package p = mPackages.get(packageName);
2808 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07002809 pi = generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 }
2811 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002812
Henrik Engström9771a312012-02-21 09:05:17 +01002813 if (pi != null && list.append(pi)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002814 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 }
2816 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002817
2818 if (i == N) {
2819 list.setLastSlice(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002821 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002822
2823 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002824 }
2825
Amith Yamasani483f3b02012-03-13 16:08:00 -07002826 @Override
Kenny Root0e2c0f32011-04-15 17:50:10 -07002827 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002828 String lastRead, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002829 if (!sUserManager.exists(userId)) return null;
Kenny Root0e2c0f32011-04-15 17:50:10 -07002830 final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
2831 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2832 final String[] keys;
2833
Kenny Root447106f2011-03-23 11:00:15 -07002834 // writer
Kenny Root0e2c0f32011-04-15 17:50:10 -07002835 synchronized (mPackages) {
2836 if (listUninstalled) {
2837 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2838 } else {
2839 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2840 }
2841
2842 Arrays.sort(keys);
2843 int i = getContinuationPoint(keys, lastRead);
2844 final int N = keys.length;
2845
2846 while (i < N) {
2847 final String packageName = keys[i++];
2848
2849 ApplicationInfo ai = null;
Amith Yamasani13593602012-03-22 16:16:17 -07002850 final PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002851 if (listUninstalled) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002852 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002853 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002854 }
2855 } else {
2856 final PackageParser.Package p = mPackages.get(packageName);
Amith Yamasani13593602012-03-22 16:16:17 -07002857 if (p != null && ps != null) {
2858 ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
2859 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 }
2861 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002862
Henrik Engström9771a312012-02-21 09:05:17 +01002863 if (ai != null && list.append(ai)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002864 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
2866 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002867
2868 if (i == N) {
2869 list.setLastSlice(true);
2870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002872
2873 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 }
2875
2876 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002877 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878
Kenny Root447106f2011-03-23 11:00:15 -07002879 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002880 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002881 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002882 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002884 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002885 if (p.applicationInfo != null
2886 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002887 && (!mSafeMode || isSystemApp(p))) {
Amith Yamasani13593602012-03-22 16:16:17 -07002888 PackageSetting ps = mSettings.mPackages.get(p.packageName);
2889 finalList.add(PackageParser.generateApplicationInfo(p, flags,
2890 ps != null ? ps.getStopped(userId) : false,
2891 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2892 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 }
2894 }
2895 }
2896
2897 return finalList;
2898 }
2899
Amith Yamasani483f3b02012-03-13 16:08:00 -07002900 @Override
2901 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002902 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002903 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 synchronized (mPackages) {
2905 final PackageParser.Provider provider = mProviders.get(name);
Amith Yamasani13593602012-03-22 16:16:17 -07002906 PackageSetting ps = provider != null
2907 ? mSettings.mPackages.get(provider.owner.packageName)
2908 : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002909 return provider != null
Amith Yamasani483f3b02012-03-13 16:08:00 -07002910 && mSettings.isEnabledLPr(provider.info, flags, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 && (!mSafeMode || (provider.info.applicationInfo.flags
2912 &ApplicationInfo.FLAG_SYSTEM) != 0)
Amith Yamasani13593602012-03-22 16:16:17 -07002913 ? PackageParser.generateProviderInfo(provider, flags,
2914 ps != null ? ps.getStopped(userId) : false,
2915 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2916 userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 : null;
2918 }
2919 }
2920
Fred Quintana718d8a22009-04-29 17:53:20 -07002921 /**
2922 * @deprecated
2923 */
Kenny Root60f7ad82011-03-22 12:49:06 -07002924 @Deprecated
2925 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07002926 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002927 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002928 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
2929 .iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002930 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 while (i.hasNext()) {
2932 Map.Entry<String, PackageParser.Provider> entry = i.next();
2933 PackageParser.Provider p = entry.getValue();
Amith Yamasani13593602012-03-22 16:16:17 -07002934 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002935
2936 if (p.syncable
2937 && (!mSafeMode || (p.info.applicationInfo.flags
2938 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2939 outNames.add(entry.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -07002940 outInfo.add(PackageParser.generateProviderInfo(p, 0,
2941 ps != null ? ps.getStopped(userId) : false,
2942 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2943 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 }
2945 }
2946 }
2947 }
2948
2949 public List<ProviderInfo> queryContentProviders(String processName,
2950 int uid, int flags) {
2951 ArrayList<ProviderInfo> finalList = null;
2952
Kenny Root447106f2011-03-23 11:00:15 -07002953 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002955 final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
Amith Yamasani483f3b02012-03-13 16:08:00 -07002956 final int userId = processName != null ?
2957 UserId.getUserId(uid) : UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002959 final PackageParser.Provider p = i.next();
Amith Yamasani13593602012-03-22 16:16:17 -07002960 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 if (p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07002962 && (processName == null
2963 || (p.info.processName.equals(processName)
Amith Yamasani483f3b02012-03-13 16:08:00 -07002964 && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
2965 && mSettings.isEnabledLPr(p.info, flags, userId)
Kenny Root447106f2011-03-23 11:00:15 -07002966 && (!mSafeMode
2967 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 if (finalList == null) {
2969 finalList = new ArrayList<ProviderInfo>(3);
2970 }
Amith Yamasani13593602012-03-22 16:16:17 -07002971 finalList.add(PackageParser.generateProviderInfo(p, flags,
2972 ps != null ? ps.getStopped(userId) : false,
2973 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2974 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976 }
2977 }
2978
2979 if (finalList != null) {
2980 Collections.sort(finalList, mProviderInitOrderSorter);
2981 }
2982
2983 return finalList;
2984 }
2985
2986 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2987 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002988 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 synchronized (mPackages) {
2990 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2991 return PackageParser.generateInstrumentationInfo(i, flags);
2992 }
2993 }
2994
2995 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2996 int flags) {
2997 ArrayList<InstrumentationInfo> finalList =
2998 new ArrayList<InstrumentationInfo>();
2999
Kenny Root447106f2011-03-23 11:00:15 -07003000 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003002 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003004 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 if (targetPackage == null
3006 || targetPackage.equals(p.info.targetPackage)) {
3007 finalList.add(PackageParser.generateInstrumentationInfo(p,
3008 flags));
3009 }
3010 }
3011 }
3012
3013 return finalList;
3014 }
3015
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003016 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07003018 if (files == null) {
3019 Log.d(TAG, "No files in app dir " + dir);
3020 return;
3021 }
3022
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003023 if (DEBUG_PACKAGE_SCANNING) {
Joe Onorato431bb222010-10-18 19:13:23 -04003024 Log.d(TAG, "Scanning app dir " + dir);
3025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026
3027 int i;
3028 for (i=0; i<files.length; i++) {
3029 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003030 if (!isPackageFilename(files[i])) {
3031 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003032 continue;
3033 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003034 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003035 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003036 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08003037 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
3038 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003039 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003040 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003041 file.delete();
3042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 }
3044 }
3045
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003046 private static File getSettingsProblemFile() {
3047 File dataDir = Environment.getDataDirectory();
3048 File systemDir = new File(dataDir, "system");
3049 File fname = new File(systemDir, "uiderrors.txt");
3050 return fname;
3051 }
3052
Kenny Rootcf0b38c2011-03-22 14:17:59 -07003053 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003055 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 FileOutputStream out = new FileOutputStream(fname, true);
3057 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003058 SimpleDateFormat formatter = new SimpleDateFormat();
3059 String dateString = formatter.format(new Date(System.currentTimeMillis()));
3060 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 pw.close();
3062 FileUtils.setPermissions(
3063 fname.toString(),
3064 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
3065 -1, -1);
3066 } catch (java.io.IOException e) {
3067 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003068 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
3070
3071 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
3072 PackageParser.Package pkg, File srcFile, int parseFlags) {
3073 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07003074 if (ps != null
3075 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07003076 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07003077 if (ps.signatures.mSignatures != null
3078 && ps.signatures.mSignatures.length != 0) {
3079 // Optimization: reuse the existing cached certificates
3080 // if the package appears to be unchanged.
3081 pkg.mSignatures = ps.signatures.mSignatures;
3082 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 }
Jeff Browne7600722010-04-07 18:28:23 -07003084
3085 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003086 } else {
Jeff Browne7600722010-04-07 18:28:23 -07003087 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
3088 }
3089
3090 if (!pp.collectCertificates(pkg, parseFlags)) {
3091 mLastScanError = pp.getParseError();
3092 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 }
3094 }
3095 return true;
3096 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 /*
3099 * Scan a package and return the newly parsed package.
3100 * Returns null in case of errors and the error code is stored in mLastScanError
3101 */
3102 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003103 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003105 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003107 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07003109 pp.setOnlyCoreApps(mOnlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003111 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 if (pkg == null) {
3113 mLastScanError = pp.getParseError();
3114 return null;
3115 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003116 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07003118 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003120 // Look to see if we already know about this package.
3121 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003122 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003123 // This package has been renamed to its original name. Let's
3124 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07003125 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003126 }
3127 // If there was no original package, see one for the real package name.
3128 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07003129 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003130 }
3131 // Check to see if this package could be hiding/updating a system
3132 // package. Must look for it either under the original or real
3133 // package name depending on our state.
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003134 updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003136 // First check if this is a system package that may involve an update
3137 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07003138 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003139 // The path has changed from what was last scanned... check the
3140 // version of the new path against what we have stored to determine
3141 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003142 if (pkg.mVersionCode < ps.versionCode) {
3143 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003144 // Ignore entry. Skip it.
3145 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003146 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003147 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003148 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3149 return null;
3150 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003151 // The current app on the system partion is better than
3152 // what we have updated to on the data partition; switch
3153 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003154 // At this point, its safely assumed that package installation for
3155 // apps in system partition will go through. If not there won't be a working
3156 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07003157 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003158 synchronized (mPackages) {
3159 // Just remove the loaded entries from package lists.
3160 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003161 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003162 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003163 + "reverting from " + ps.codePathString
3164 + ": new version " + pkg.mVersionCode
3165 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003166
3167 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3168 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Kenny Root208d3412012-05-07 19:42:35 -07003169 synchronized (mInstaller) {
3170 args.cleanUpResourcesLI();
3171 }
3172 synchronized (mPackages) {
3173 mSettings.enableSystemPackageLPw(ps.name);
3174 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 }
3177 }
Kenny Root208d3412012-05-07 19:42:35 -07003178
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003179 if (updatedPkg != null) {
Kenny Root208d3412012-05-07 19:42:35 -07003180 // An updated system app will not have the PARSE_IS_SYSTEM flag set
3181 // initially
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003182 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
3183 }
3184 // Verify certificates against what was last scanned
3185 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003186 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003187 return null;
3188 }
Kenny Root208d3412012-05-07 19:42:35 -07003189
3190 /*
3191 * A new system app appeared, but we already had a non-system one of the
3192 * same name installed earlier.
3193 */
3194 boolean shouldHideSystemApp = false;
3195 if (updatedPkg == null && ps != null
3196 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
3197 /*
3198 * Check to make sure the signatures match first. If they don't,
3199 * wipe the installed application and its data.
3200 */
3201 if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
3202 != PackageManager.SIGNATURE_MATCH) {
3203 deletePackageLI(pkg.packageName, true, 0, null, false);
3204 ps = null;
3205 } else {
3206 /*
3207 * If the newly-added system app is an older version than the
3208 * already installed version, hide it. It will be scanned later
3209 * and re-added like an update.
3210 */
3211 if (pkg.mVersionCode < ps.versionCode) {
3212 shouldHideSystemApp = true;
3213 } else {
3214 /*
3215 * The newly found system app is a newer version that the
3216 * one previously installed. Simply remove the
3217 * already-installed application and replace it with our own
3218 * while keeping the application data.
3219 */
3220 Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
3221 + ps.codePathString + ": new version " + pkg.mVersionCode
3222 + " better than installed " + ps.versionCode);
Kenny Root88670d82012-05-09 15:47:35 -07003223 InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
3224 ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
Kenny Root208d3412012-05-07 19:42:35 -07003225 synchronized (mInstaller) {
3226 args.cleanUpResourcesLI();
3227 }
3228 }
3229 }
3230 }
3231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003232 // The apk is forward locked (not public) if its code and resources
3233 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003234 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003236 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07003237 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003238
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003239 String codePath = null;
3240 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003241 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
3242 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003243 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003244 } else {
3245 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003246 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003247 }
3248 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003249 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003250 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003251 codePath = pkg.mScanPath;
3252 // Set application objects path explicitly.
3253 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 // Note that we invoke the following method only if we are about to unpack an application
Kenny Root208d3412012-05-07 19:42:35 -07003255 PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
3256 | SCAN_UPDATE_SIGNATURE, currentTime);
3257
3258 /*
3259 * If the system app should be overridden by a previously installed
3260 * data, hide the system app now and let the /data/app scan pick it up
3261 * again.
3262 */
3263 if (shouldHideSystemApp) {
3264 synchronized (mPackages) {
3265 /*
3266 * We have to grant systems permissions before we hide, because
3267 * grantPermissions will assume the package update is trying to
3268 * expand its permissions.
3269 */
3270 grantPermissionsLPw(pkg, true);
3271 mSettings.disableSystemPackageLPw(pkg.packageName);
3272 }
3273 }
3274
3275 return scannedPkg;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003276 }
3277
Kenny Root85387d72010-08-26 10:13:11 -07003278 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
3279 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003280 pkg.mPath = pkg.mScanPath = destCodePath;
3281 pkg.applicationInfo.sourceDir = destCodePath;
3282 pkg.applicationInfo.publicSourceDir = destResPath;
3283 }
3284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 private static String fixProcessName(String defProcessName,
3286 String processName, int uid) {
3287 if (processName == null) {
3288 return defProcessName;
3289 }
3290 return processName;
3291 }
3292
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003293 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003294 PackageParser.Package pkg) {
3295 if (pkgSetting.signatures.mSignatures != null) {
3296 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07003297 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003298 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003299 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003300 + " signatures do not match the previously installed version; ignoring!");
3301 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003302 return false;
3303 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003304 }
3305 // Check for shared user signatures
3306 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003307 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003308 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3309 Slog.e(TAG, "Package " + pkg.packageName
3310 + " has no signatures that match those in shared user "
3311 + pkgSetting.sharedUser.name + "; ignoring!");
3312 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
3313 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 }
3316 return true;
3317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003318
Kenny Root461ff1f2011-08-09 09:43:03 -07003319 /**
3320 * Enforces that only the system UID or root's UID can call a method exposed
3321 * via Binder.
3322 *
3323 * @param message used as message if SecurityException is thrown
3324 * @throws SecurityException if the caller is not system or root
3325 */
3326 private static final void enforceSystemOrRoot(String message) {
3327 final int uid = Binder.getCallingUid();
3328 if (uid != Process.SYSTEM_UID && uid != 0) {
3329 throw new SecurityException(message);
3330 }
3331 }
3332
Dianne Hackborn661cd522011-08-22 00:26:20 -07003333 public void performBootDexOpt() {
3334 ArrayList<PackageParser.Package> pkgs = null;
3335 synchronized (mPackages) {
3336 if (mDeferredDexOpt.size() > 0) {
3337 pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
3338 mDeferredDexOpt.clear();
3339 }
3340 }
3341 if (pkgs != null) {
3342 for (int i=0; i<pkgs.size(); i++) {
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003343 if (!isFirstBoot()) {
3344 try {
3345 ActivityManagerNative.getDefault().showBootMessage(
3346 mContext.getResources().getString(
3347 com.android.internal.R.string.android_upgrading_apk,
3348 i+1, pkgs.size()), true);
3349 } catch (RemoteException e) {
3350 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003351 }
3352 PackageParser.Package p = pkgs.get(i);
3353 synchronized (mInstallLock) {
3354 if (!p.mDidDexOpt) {
3355 performDexOptLI(p, false, false);
3356 }
3357 }
3358 }
3359 }
3360 }
3361
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003362 public boolean performDexOpt(String packageName) {
Kenny Root461ff1f2011-08-09 09:43:03 -07003363 enforceSystemOrRoot("Only the system can request dexopt be performed");
3364
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003365 if (!mNoDexOpt) {
3366 return false;
3367 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003368
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003369 PackageParser.Package p;
3370 synchronized (mPackages) {
3371 p = mPackages.get(packageName);
3372 if (p == null || p.mDidDexOpt) {
3373 return false;
3374 }
3375 }
3376 synchronized (mInstallLock) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003377 return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003378 }
3379 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003380
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003381 static final int DEX_OPT_SKIPPED = 0;
3382 static final int DEX_OPT_PERFORMED = 1;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003383 static final int DEX_OPT_DEFERRED = 2;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003384 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003385
Dianne Hackborn661cd522011-08-22 00:26:20 -07003386 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003387 boolean performed = false;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003388 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003389 String path = pkg.mScanPath;
3390 int ret = 0;
3391 try {
3392 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003393 if (!forceDex && defer) {
3394 mDeferredDexOpt.add(pkg);
3395 return DEX_OPT_DEFERRED;
3396 } else {
3397 Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
3398 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
3399 !isForwardLocked(pkg));
3400 pkg.mDidDexOpt = true;
3401 performed = true;
3402 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003403 }
3404 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003405 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003406 ret = -1;
3407 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07003408 Slog.w(TAG, "IOException reading apk: " + path, e);
3409 ret = -1;
3410 } catch (dalvik.system.StaleDexCacheError e) {
3411 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
3412 ret = -1;
3413 } catch (Exception e) {
3414 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003415 ret = -1;
3416 }
3417 if (ret < 0) {
3418 //error from installer
3419 return DEX_OPT_FAILED;
3420 }
3421 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003422
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003423 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
3424 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08003425
Kenny Root447106f2011-03-23 11:00:15 -07003426 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003427 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003428 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003429 + " to " + newPkg.packageName
3430 + ": old package not in system partition");
3431 return false;
3432 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003433 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003434 + " to " + newPkg.packageName
3435 + ": old package still exists");
3436 return false;
3437 }
3438 return true;
3439 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003440
Amith Yamasani0b285492011-04-14 17:35:23 -07003441 File getDataPathForUser(int userId) {
3442 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003443 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003444
3445 private File getDataPathForPackage(String packageName, int userId) {
Kenny Root9c8625e2011-07-25 09:42:22 -07003446 /*
3447 * Until we fully support multiple users, return the directory we
3448 * previously would have. The PackageManagerTests will need to be
3449 * revised when this is changed back..
3450 */
3451 if (userId == 0) {
3452 return new File(mAppDataDir, packageName);
3453 } else {
3454 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003455 + File.separator + packageName);
Kenny Root9c8625e2011-07-25 09:42:22 -07003456 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003457 }
3458
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003459 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003460 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003461 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08003462 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
3463 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003464 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003465 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003466 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
3467 return null;
3468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 mScanningPath = scanFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3472 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
3473 }
3474
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003475 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 synchronized (mPackages) {
3477 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003478 Slog.w(TAG, "*************************************************");
3479 Slog.w(TAG, "Core android package being redefined. Skipping.");
3480 Slog.w(TAG, " file=" + mScanningPath);
3481 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003482 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3483 return null;
3484 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 // Set up information for our fall-back user intent resolution
3487 // activity.
3488 mPlatformPackage = pkg;
3489 pkg.mVersionCode = mSdkVersion;
3490 mAndroidApplication = pkg.applicationInfo;
3491 mResolveActivity.applicationInfo = mAndroidApplication;
3492 mResolveActivity.name = ResolverActivity.class.getName();
3493 mResolveActivity.packageName = mAndroidApplication.packageName;
3494 mResolveActivity.processName = mAndroidApplication.processName;
3495 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3496 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08003497 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 mResolveActivity.exported = true;
3499 mResolveActivity.enabled = true;
3500 mResolveInfo.activityInfo = mResolveActivity;
3501 mResolveInfo.priority = 0;
3502 mResolveInfo.preferredOrder = 0;
3503 mResolveInfo.match = 0;
3504 mResolveComponentName = new ComponentName(
3505 mAndroidApplication.packageName, mResolveActivity.name);
3506 }
3507 }
3508
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003509 if (DEBUG_PACKAGE_SCANNING) {
3510 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3511 Log.d(TAG, "Scanning package " + pkg.packageName);
3512 }
3513
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003514 if (mPackages.containsKey(pkg.packageName)
3515 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003516 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003517 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3519 return null;
3520 }
3521
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003522 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003523 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
3524 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 SharedUserSetting suid = null;
3527 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003528
Kenny Root502e9a42011-01-10 13:48:15 -08003529 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003530 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08003531 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003532 pkg.mRealPackage = null;
3533 pkg.mAdoptPermissions = null;
3534 }
Kenny Root502e9a42011-01-10 13:48:15 -08003535
Kenny Root447106f2011-03-23 11:00:15 -07003536 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 synchronized (mPackages) {
3538 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07003539 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
3540 if (mTmpSharedLibraries == null ||
3541 mTmpSharedLibraries.length < mSharedLibraries.size()) {
3542 mTmpSharedLibraries = new String[mSharedLibraries.size()];
3543 }
3544 int num = 0;
3545 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
3546 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003547 final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003549 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07003551 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
3553 return null;
3554 }
Dianne Hackborn49237342009-08-27 20:08:01 -07003555 mTmpSharedLibraries[num] = file;
3556 num++;
3557 }
3558 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
3559 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003560 final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
Dianne Hackborn49237342009-08-27 20:08:01 -07003561 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003562 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07003563 + " desires unavailable shared library "
3564 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
3565 } else {
3566 mTmpSharedLibraries[num] = file;
3567 num++;
3568 }
3569 }
3570 if (num > 0) {
3571 pkg.usesLibraryFiles = new String[num];
3572 System.arraycopy(mTmpSharedLibraries, 0,
3573 pkg.usesLibraryFiles, 0, num);
3574 }
Kenny Root1683afa2011-01-07 14:27:50 -08003575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 if (pkg.mSharedUserId != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003578 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 pkg.applicationInfo.flags, true);
3580 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003581 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 + " for shared user failed");
3583 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3584 return null;
3585 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003586 if (DEBUG_PACKAGE_SCANNING) {
3587 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3588 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
3589 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 }
3591 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003592
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003593 // Check if we are renaming from an original package name.
3594 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003595 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08003596 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003597 // This package may need to be renamed to a previously
3598 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07003599 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003600 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003601 // This package had originally been installed as the
3602 // original name, and we have already taken care of
3603 // transitioning to the new one. Just update the new
3604 // one to continue using the old name.
3605 realName = pkg.mRealPackage;
3606 if (!pkg.packageName.equals(renamed)) {
3607 // Callers into this function may have already taken
3608 // care of renaming the package; only do it here if
3609 // it is not already done.
3610 pkg.setPackageName(renamed);
3611 }
3612
Dianne Hackbornc1552392010-03-03 16:19:01 -08003613 } else {
3614 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07003615 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08003616 pkg.mOriginalPackages.get(i))) != null) {
3617 // We do have the package already installed under its
3618 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07003619 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08003620 // New package is not compatible with original.
3621 origPackage = null;
3622 continue;
3623 } else if (origPackage.sharedUser != null) {
3624 // Make sure uid is compatible between packages.
3625 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003626 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003627 + " to " + pkg.packageName + ": old uid "
3628 + origPackage.sharedUser.name
3629 + " differs from " + pkg.mSharedUserId);
3630 origPackage = null;
3631 continue;
3632 }
3633 } else {
3634 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3635 + pkg.packageName + " to old name " + origPackage.name);
3636 }
3637 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003638 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003639 }
3640 }
3641 }
3642
3643 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003644 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003645 + " was transferred to another, but its .apk remains");
3646 }
3647
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003648 // Just create the setting, don't add it yet. For already existing packages
3649 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07003650 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003651 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3652 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003654 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3656 return null;
3657 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003658
3659 if (pkgSetting.origPackage != null) {
3660 // If we are first transitioning from an original package,
3661 // fix up the new package's name now. We need to do this after
3662 // looking up the package under its new name, so getPackageLP
3663 // can take care of fiddling things correctly.
3664 pkg.setPackageName(origPackage.name);
3665
3666 // File a report about this.
3667 String msg = "New package " + pkgSetting.realName
3668 + " renamed to replace old package " + pkgSetting.name;
3669 reportSettingsProblem(Log.WARN, msg);
3670
3671 // Make a note of it.
3672 mTransferedPackages.add(origPackage.name);
3673
3674 // No longer need to retain this.
3675 pkgSetting.origPackage = null;
3676 }
3677
3678 if (realName != null) {
3679 // Make a note of it.
3680 mTransferedPackages.add(pkg.packageName);
3681 }
3682
Kenny Rootc52d6fd2012-05-07 23:04:52 -07003683 if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3685 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003686
Amith Yamasani13593602012-03-22 16:16:17 -07003687 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003689
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003690 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003691 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 return null;
3693 }
3694 // The signature has changed, but this package is in the system
3695 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003696 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 // However... if this package is part of a shared user, but it
3698 // doesn't match the signature of the shared user, let's fail.
3699 // What this means is that you can't change the signatures
3700 // associated with an overall shared user, which doesn't seem all
3701 // that unreasonable.
3702 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003703 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003704 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3705 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3707 return null;
3708 }
3709 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003710 // File a report about this.
3711 String msg = "System package " + pkg.packageName
3712 + " signature changed; retaining data.";
3713 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003715
The Android Open Source Project10592532009-03-18 17:39:46 -07003716 // Verify that this new package doesn't have any content providers
3717 // that conflict with existing packages. Only do this if the
3718 // package isn't already installed, since we don't want to break
3719 // things that are installed.
3720 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08003721 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07003722 int i;
3723 for (i=0; i<N; i++) {
3724 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003725 if (p.info.authority != null) {
3726 String names[] = p.info.authority.split(";");
3727 for (int j = 0; j < names.length; j++) {
3728 if (mProviders.containsKey(names[j])) {
3729 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003730 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003731 " (in package " + pkg.applicationInfo.packageName +
3732 ") is already used by "
3733 + ((other != null && other.getComponentName() != null)
3734 ? other.getComponentName().getPackageName() : "?"));
3735 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3736 return null;
3737 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003738 }
3739 }
3740 }
3741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003742
Kenny Root447106f2011-03-23 11:00:15 -07003743 if (pkg.mAdoptPermissions != null) {
3744 // This package wants to adopt ownership of permissions from
3745 // another package.
3746 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
3747 final String origName = pkg.mAdoptPermissions.get(i);
3748 final PackageSetting orig = mSettings.peekPackageLPr(origName);
3749 if (orig != null) {
3750 if (verifyPackageUpdateLPr(orig, pkg)) {
3751 Slog.i(TAG, "Adopting permissions from " + origName + " to "
3752 + pkg.packageName);
3753 mSettings.transferPermissionsLPw(origName, pkg.packageName);
3754 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003755 }
3756 }
3757 }
3758 }
Kenny Root447106f2011-03-23 11:00:15 -07003759
3760 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003761
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003762 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 pkg.applicationInfo.processName = fixProcessName(
3765 pkg.applicationInfo.packageName,
3766 pkg.applicationInfo.processName,
3767 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003768
3769 File dataPath;
3770 if (mPlatformPackage == pkg) {
3771 // The system package is special.
3772 dataPath = new File (Environment.getDataDirectory(), "system");
3773 pkg.applicationInfo.dataDir = dataPath.getPath();
3774 } else {
3775 // This is a normal package, need to make its data directory.
Amith Yamasani0b285492011-04-14 17:35:23 -07003776 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003777
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003778 boolean uidError = false;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 if (dataPath.exists()) {
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003781 // XXX should really do this check for each user.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003782 mOutPermissions[1] = 0;
3783 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003784
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003785 // If we have mismatched owners for the data path, we have a problem.
Jeff Brown10e89712011-07-08 18:52:57 -07003786 if (mOutPermissions[1] != pkg.applicationInfo.uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 boolean recovered = false;
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003788 if (mOutPermissions[1] == 0) {
3789 // The directory somehow became owned by root. Wow.
3790 // This is probably because the system was stopped while
3791 // installd was in the middle of messing with its libs
3792 // directory. Ask installd to fix that.
3793 int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
3794 pkg.applicationInfo.uid);
3795 if (ret >= 0) {
3796 recovered = true;
3797 String msg = "Package " + pkg.packageName
3798 + " unexpectedly changed to uid 0; recovered to " +
3799 + pkg.applicationInfo.uid;
3800 reportSettingsProblem(Log.WARN, msg);
3801 }
3802 }
3803 if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
3804 || (scanMode&SCAN_BOOTING) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805 // If this is a system app, we can at least delete its
3806 // current data so the application will still work.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003807 int ret = mInstaller.remove(pkgName, 0);
3808 if (ret >= 0) {
3809 // TODO: Kill the processes first
3810 // Remove the data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003811 sUserManager.removePackageForAllUsers(pkgName);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003812 // Old data gone!
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003813 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
3814 ? "System package " : "Third party package ";
3815 String msg = prefix + pkg.packageName
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003816 + " has changed from uid: "
3817 + mOutPermissions[1] + " to "
3818 + pkg.applicationInfo.uid + "; old data erased";
3819 reportSettingsProblem(Log.WARN, msg);
3820 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003821
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003822 // And now re-install the app.
3823 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3824 pkg.applicationInfo.uid);
3825 if (ret == -1) {
3826 // Ack should not happen!
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003827 msg = prefix + pkg.packageName
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003828 + " could not have data directory re-created after delete.";
3829 reportSettingsProblem(Log.WARN, msg);
3830 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3831 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003833 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003834 sUserManager.installPackageForAllUsers(pkgName,
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003835 pkg.applicationInfo.uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 if (!recovered) {
3838 mHasSystemUidErrors = true;
3839 }
Dianne Hackbornd0c5f512012-06-07 16:53:59 -07003840 } else if (!recovered) {
3841 // If we allow this install to proceed, we will be broken.
3842 // Abort, abort!
3843 mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
3844 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 }
3846 if (!recovered) {
3847 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3848 + pkg.applicationInfo.uid + "/fs_"
3849 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003850 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 String msg = "Package " + pkg.packageName
3852 + " has mismatched uid: "
3853 + mOutPermissions[1] + " on disk, "
3854 + pkg.applicationInfo.uid + " in settings";
Kenny Root447106f2011-03-23 11:00:15 -07003855 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003857 mSettings.mReadMessages.append(msg);
3858 mSettings.mReadMessages.append('\n');
3859 uidError = true;
3860 if (!pkgSetting.uidError) {
3861 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 }
3864 }
3865 }
3866 pkg.applicationInfo.dataDir = dataPath.getPath();
3867 } else {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003868 if (DEBUG_PACKAGE_SCANNING) {
3869 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3870 Log.v(TAG, "Want this data dir: " + dataPath);
3871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 //invoke installer to do the actual installation
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003873 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3874 pkg.applicationInfo.uid);
3875 if (ret < 0) {
3876 // Error from installer
3877 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3878 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003880 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003881 sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 if (dataPath.exists()) {
3884 pkg.applicationInfo.dataDir = dataPath.getPath();
3885 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003886 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 pkg.applicationInfo.dataDir = null;
3888 }
3889 }
Kenny Root85387d72010-08-26 10:13:11 -07003890
3891 /*
3892 * Set the data dir to the default "/data/data/<package name>/lib"
3893 * if we got here without anyone telling us different (e.g., apps
3894 * stored on SD card have their native libraries stored in the ASEC
3895 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003896 *
3897 * This happens during an upgrade from a package settings file that
3898 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003899 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003900 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3901 if (pkgSetting.nativeLibraryPathString == null) {
3902 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3903 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3904 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3905 } else {
3906 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3907 }
Kenny Root85387d72010-08-26 10:13:11 -07003908 }
3909
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003910 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003911 }
3912
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003913 String path = scanFile.getPath();
3914 /* Note: We don't want to unpack the native binaries for
3915 * system applications, unless they have been updated
3916 * (the binaries are already under /system/lib).
3917 * Also, don't unpack libs for apps on the external card
3918 * since they should have their libraries in the ASEC
3919 * container already.
3920 *
3921 * In other words, we're going to unpack the binaries
3922 * only for non-system apps and system app upgrades.
3923 */
3924 if (pkg.applicationInfo.nativeLibraryDir != null) {
3925 try {
3926 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07003927 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07003928
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003929 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3930 /*
3931 * Upgrading from a previous version of the OS sometimes
3932 * leaves native libraries in the /data/data/<app>/lib
3933 * directory for system apps even when they shouldn't be.
3934 * Recent changes in the JNI library search path
3935 * necessitates we remove those to match previous behavior.
3936 */
3937 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
3938 Log.i(TAG, "removed obsolete native libraries for system package "
3939 + path);
Kenny Root831baa22010-10-05 12:29:25 -07003940 }
Kenny Root5832ead2011-08-02 15:47:08 -07003941 } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003942 .equals(dataPathString)) {
3943 /*
Kenny Root66269ea2011-07-12 14:14:01 -07003944 * Make sure the native library dir isn't a symlink to
3945 * something. If it is, ask installd to remove it and create
3946 * a directory so we can copy to it afterwards.
3947 */
3948 boolean isSymLink;
3949 try {
3950 isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
3951 } catch (ErrnoException e) {
3952 // This shouldn't happen, but we'll fail-safe.
3953 isSymLink = true;
3954 }
3955 if (isSymLink) {
3956 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3957 }
3958
3959 /*
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003960 * If this is an internal application or our
3961 * nativeLibraryPath points to our data directory, unpack
Kenny Root66269ea2011-07-12 14:14:01 -07003962 * the libraries if necessary.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003963 */
Kenny Root66269ea2011-07-12 14:14:01 -07003964 NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003965 } else {
3966 Slog.i(TAG, "Linking native library dir for " + path);
3967 mInstaller.linkNativeLibraryDirectory(dataPathString,
3968 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003969 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003970 } catch (IOException ioe) {
3971 Log.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003973 }
3974 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003975
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003976 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003977 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0)
3978 == DEX_OPT_FAILED) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003979 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3980 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 }
3982 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 if (mFactoryTest && pkg.requestedPermissions.contains(
3985 android.Manifest.permission.FACTORY_TEST)) {
3986 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3987 }
3988
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003989 // Request the ActivityManager to kill the process(only for existing packages)
3990 // so that we do not end up in a confused state while the user is still using the older
3991 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003992 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003993 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003994 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003995 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003996
Kenny Root447106f2011-03-23 11:00:15 -07003997 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003998 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003999 // We don't expect installation to fail beyond this point,
4000 if ((scanMode&SCAN_MONITOR) != 0) {
4001 mAppDirs.put(pkg.mPath, pkg);
4002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07004004 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07004006 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004007 // Make sure we don't accidentally delete its data.
4008 mSettings.mPackagesToBeCleaned.remove(pkgName);
4009
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004010 // Take care of first install / last update times.
4011 if (currentTime != 0) {
4012 if (pkgSetting.firstInstallTime == 0) {
4013 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
4014 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
4015 pkgSetting.lastUpdateTime = currentTime;
4016 }
4017 } else if (pkgSetting.firstInstallTime == 0) {
4018 // We need *something*. Take time time stamp of the file.
4019 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
4020 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
4021 if (scanFileTime != pkgSetting.timeStamp) {
4022 // A package on the system image has changed; consider this
4023 // to be an update.
4024 pkgSetting.lastUpdateTime = scanFileTime;
4025 }
4026 }
4027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 int N = pkg.providers.size();
4029 StringBuilder r = null;
4030 int i;
4031 for (i=0; i<N; i++) {
4032 PackageParser.Provider p = pkg.providers.get(i);
4033 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
4034 p.info.processName, pkg.applicationInfo.uid);
4035 mProvidersByComponent.put(new ComponentName(p.info.packageName,
4036 p.info.name), p);
4037 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004038 if (p.info.authority != null) {
4039 String names[] = p.info.authority.split(";");
4040 p.info.authority = null;
4041 for (int j = 0; j < names.length; j++) {
4042 if (j == 1 && p.syncable) {
4043 // We only want the first authority for a provider to possibly be
4044 // syncable, so if we already added this provider using a different
4045 // authority clear the syncable flag. We copy the provider before
4046 // changing it because the mProviders object contains a reference
4047 // to a provider that we don't want to change.
4048 // Only do this for the second authority since the resulting provider
4049 // object can be the same for all future authorities for this provider.
4050 p = new PackageParser.Provider(p);
4051 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004053 if (!mProviders.containsKey(names[j])) {
4054 mProviders.put(names[j], p);
4055 if (p.info.authority == null) {
4056 p.info.authority = names[j];
4057 } else {
4058 p.info.authority = p.info.authority + ";" + names[j];
4059 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004060 if (DEBUG_PACKAGE_SCANNING) {
4061 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
4062 Log.d(TAG, "Registered content provider: " + names[j]
4063 + ", className = " + p.info.name + ", isSyncable = "
4064 + p.info.isSyncable);
4065 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004066 } else {
4067 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004068 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08004069 " (in package " + pkg.applicationInfo.packageName +
4070 "): name already used by "
4071 + ((other != null && other.getComponentName() != null)
4072 ? other.getComponentName().getPackageName() : "?"));
4073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 }
4075 }
4076 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4077 if (r == null) {
4078 r = new StringBuilder(256);
4079 } else {
4080 r.append(' ');
4081 }
4082 r.append(p.info.name);
4083 }
4084 }
4085 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004086 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 N = pkg.services.size();
4090 r = null;
4091 for (i=0; i<N; i++) {
4092 PackageParser.Service s = pkg.services.get(i);
4093 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
4094 s.info.processName, pkg.applicationInfo.uid);
4095 mServices.addService(s);
4096 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4097 if (r == null) {
4098 r = new StringBuilder(256);
4099 } else {
4100 r.append(' ');
4101 }
4102 r.append(s.info.name);
4103 }
4104 }
4105 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004106 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 N = pkg.receivers.size();
4110 r = null;
4111 for (i=0; i<N; i++) {
4112 PackageParser.Activity a = pkg.receivers.get(i);
4113 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4114 a.info.processName, pkg.applicationInfo.uid);
4115 mReceivers.addActivity(a, "receiver");
4116 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4117 if (r == null) {
4118 r = new StringBuilder(256);
4119 } else {
4120 r.append(' ');
4121 }
4122 r.append(a.info.name);
4123 }
4124 }
4125 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004126 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 N = pkg.activities.size();
4130 r = null;
4131 for (i=0; i<N; i++) {
4132 PackageParser.Activity a = pkg.activities.get(i);
4133 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
4134 a.info.processName, pkg.applicationInfo.uid);
4135 mActivities.addActivity(a, "activity");
4136 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4137 if (r == null) {
4138 r = new StringBuilder(256);
4139 } else {
4140 r.append(' ');
4141 }
4142 r.append(a.info.name);
4143 }
4144 }
4145 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004146 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 N = pkg.permissionGroups.size();
4150 r = null;
4151 for (i=0; i<N; i++) {
4152 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
4153 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
4154 if (cur == null) {
4155 mPermissionGroups.put(pg.info.name, pg);
4156 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4157 if (r == null) {
4158 r = new StringBuilder(256);
4159 } else {
4160 r.append(' ');
4161 }
4162 r.append(pg.info.name);
4163 }
4164 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004165 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 + pg.info.packageName + " ignored: original from "
4167 + cur.info.packageName);
4168 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4169 if (r == null) {
4170 r = new StringBuilder(256);
4171 } else {
4172 r.append(' ');
4173 }
4174 r.append("DUP:");
4175 r.append(pg.info.name);
4176 }
4177 }
4178 }
4179 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004180 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 N = pkg.permissions.size();
4184 r = null;
4185 for (i=0; i<N; i++) {
4186 PackageParser.Permission p = pkg.permissions.get(i);
4187 HashMap<String, BasePermission> permissionMap =
4188 p.tree ? mSettings.mPermissionTrees
4189 : mSettings.mPermissions;
4190 p.group = mPermissionGroups.get(p.info.group);
4191 if (p.info.group == null || p.group != null) {
4192 BasePermission bp = permissionMap.get(p.info.name);
4193 if (bp == null) {
4194 bp = new BasePermission(p.info.name, p.info.packageName,
4195 BasePermission.TYPE_NORMAL);
4196 permissionMap.put(p.info.name, bp);
4197 }
4198 if (bp.perm == null) {
4199 if (bp.sourcePackage == null
4200 || bp.sourcePackage.equals(p.info.packageName)) {
4201 BasePermission tree = findPermissionTreeLP(p.info.name);
4202 if (tree == null
4203 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004204 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 bp.perm = p;
4206 bp.uid = pkg.applicationInfo.uid;
4207 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4208 if (r == null) {
4209 r = new StringBuilder(256);
4210 } else {
4211 r.append(' ');
4212 }
4213 r.append(p.info.name);
4214 }
4215 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004216 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 + p.info.packageName + " ignored: base tree "
4218 + tree.name + " is from package "
4219 + tree.sourcePackage);
4220 }
4221 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004222 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 + p.info.packageName + " ignored: original from "
4224 + bp.sourcePackage);
4225 }
4226 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4227 if (r == null) {
4228 r = new StringBuilder(256);
4229 } else {
4230 r.append(' ');
4231 }
4232 r.append("DUP:");
4233 r.append(p.info.name);
4234 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004235 if (bp.perm == p) {
4236 bp.protectionLevel = p.info.protectionLevel;
4237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004239 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 + p.info.packageName + " ignored: no group "
4241 + p.group);
4242 }
4243 }
4244 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004245 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004248 N = pkg.instrumentation.size();
4249 r = null;
4250 for (i=0; i<N; i++) {
4251 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
4252 a.info.packageName = pkg.applicationInfo.packageName;
4253 a.info.sourceDir = pkg.applicationInfo.sourceDir;
4254 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
4255 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07004256 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004257 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4259 if (r == null) {
4260 r = new StringBuilder(256);
4261 } else {
4262 r.append(' ');
4263 }
4264 r.append(a.info.name);
4265 }
4266 }
4267 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004268 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004270
Dianne Hackborn854060af2009-07-09 18:14:31 -07004271 if (pkg.protectedBroadcasts != null) {
4272 N = pkg.protectedBroadcasts.size();
4273 for (i=0; i<N; i++) {
4274 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
4275 }
4276 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 pkgSetting.setTimeStamp(scanFileTime);
4279 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 return pkg;
4282 }
4283
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004284 private void killApplication(String pkgName, int uid) {
4285 // Request the ActivityManager to kill the process(only for existing packages)
4286 // so that we do not end up in a confused state while the user is still using the older
4287 // version of the application while the new one gets installed.
4288 IActivityManager am = ActivityManagerNative.getDefault();
4289 if (am != null) {
4290 try {
4291 am.killApplicationWithUid(pkgName, uid);
4292 } catch (RemoteException e) {
4293 }
4294 }
4295 }
4296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004298 if (DEBUG_INSTALL) {
4299 if (chatty)
4300 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
4301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302
Kenny Root447106f2011-03-23 11:00:15 -07004303 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004305 mPackages.remove(pkg.applicationInfo.packageName);
4306 if (pkg.mPath != null) {
4307 mAppDirs.remove(pkg.mPath);
4308 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 int N = pkg.providers.size();
4311 StringBuilder r = null;
4312 int i;
4313 for (i=0; i<N; i++) {
4314 PackageParser.Provider p = pkg.providers.get(i);
4315 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
4316 p.info.name));
4317 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 /* The is another ContentProvider with this authority when
4320 * this app was installed so this authority is null,
4321 * Ignore it as we don't have to unregister the provider.
4322 */
4323 continue;
4324 }
4325 String names[] = p.info.authority.split(";");
4326 for (int j = 0; j < names.length; j++) {
4327 if (mProviders.get(names[j]) == p) {
4328 mProviders.remove(names[j]);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004329 if (DEBUG_REMOVE) {
4330 if (chatty)
4331 Log.d(TAG, "Unregistered content provider: " + names[j]
4332 + ", className = " + p.info.name + ", isSyncable = "
4333 + p.info.isSyncable);
4334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 }
4336 }
4337 if (chatty) {
4338 if (r == null) {
4339 r = new StringBuilder(256);
4340 } else {
4341 r.append(' ');
4342 }
4343 r.append(p.info.name);
4344 }
4345 }
4346 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004347 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 N = pkg.services.size();
4351 r = null;
4352 for (i=0; i<N; i++) {
4353 PackageParser.Service s = pkg.services.get(i);
4354 mServices.removeService(s);
4355 if (chatty) {
4356 if (r == null) {
4357 r = new StringBuilder(256);
4358 } else {
4359 r.append(' ');
4360 }
4361 r.append(s.info.name);
4362 }
4363 }
4364 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004365 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 N = pkg.receivers.size();
4369 r = null;
4370 for (i=0; i<N; i++) {
4371 PackageParser.Activity a = pkg.receivers.get(i);
4372 mReceivers.removeActivity(a, "receiver");
4373 if (chatty) {
4374 if (r == null) {
4375 r = new StringBuilder(256);
4376 } else {
4377 r.append(' ');
4378 }
4379 r.append(a.info.name);
4380 }
4381 }
4382 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004383 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 N = pkg.activities.size();
4387 r = null;
4388 for (i=0; i<N; i++) {
4389 PackageParser.Activity a = pkg.activities.get(i);
4390 mActivities.removeActivity(a, "activity");
4391 if (chatty) {
4392 if (r == null) {
4393 r = new StringBuilder(256);
4394 } else {
4395 r.append(' ');
4396 }
4397 r.append(a.info.name);
4398 }
4399 }
4400 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004401 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 N = pkg.permissions.size();
4405 r = null;
4406 for (i=0; i<N; i++) {
4407 PackageParser.Permission p = pkg.permissions.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 BasePermission bp = mSettings.mPermissions.get(p.info.name);
4409 if (bp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 bp = mSettings.mPermissionTrees.get(p.info.name);
4411 }
4412 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004413 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 if (chatty) {
4415 if (r == null) {
4416 r = new StringBuilder(256);
4417 } else {
4418 r.append(' ');
4419 }
4420 r.append(p.info.name);
4421 }
4422 }
4423 }
4424 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004425 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 N = pkg.instrumentation.size();
4429 r = null;
4430 for (i=0; i<N; i++) {
4431 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004432 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 if (chatty) {
4434 if (r == null) {
4435 r = new StringBuilder(256);
4436 } else {
4437 r.append(' ');
4438 }
4439 r.append(a.info.name);
4440 }
4441 }
4442 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004443 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 }
4445 }
4446 }
4447
4448 private static final boolean isPackageFilename(String name) {
4449 return name != null && name.endsWith(".apk");
4450 }
4451
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004452 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
4453 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
4454 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
4455 return true;
4456 }
4457 }
4458 return false;
4459 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004460
4461 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
4462 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
4463 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
4464
Kenny Root447106f2011-03-23 11:00:15 -07004465 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08004466 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07004468 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004469 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004470 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004471 if (bp.packageSetting == null) {
4472 // We may not yet have parsed the package, so just see if
4473 // we still know about its settings.
4474 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4475 }
4476 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004477 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 + " from package " + bp.sourcePackage);
4479 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004480 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4481 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4482 Slog.i(TAG, "Removing old permission tree: " + bp.name
4483 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004484 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004485 it.remove();
4486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 }
4488 }
4489
4490 // Make sure all dynamic permissions have been assigned to a package,
4491 // and make sure there are no dangling permissions.
4492 it = mSettings.mPermissions.values().iterator();
4493 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004494 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 if (bp.type == BasePermission.TYPE_DYNAMIC) {
4496 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
4497 + bp.name + " pkg=" + bp.sourcePackage
4498 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004499 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004500 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07004501 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004502 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 bp.perm = new PackageParser.Permission(tree.perm.owner,
4504 new PermissionInfo(bp.pendingInfo));
4505 bp.perm.info.packageName = tree.perm.info.packageName;
4506 bp.perm.info.name = bp.name;
4507 bp.uid = tree.uid;
4508 }
4509 }
4510 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004511 if (bp.packageSetting == null) {
4512 // We may not yet have parsed the package, so just see if
4513 // we still know about its settings.
4514 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4515 }
4516 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004517 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 + " from package " + bp.sourcePackage);
4519 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004520 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4521 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4522 Slog.i(TAG, "Removing old permission: " + bp.name
4523 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004524 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004525 it.remove();
4526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
4528 }
4529
4530 // Now update the permissions for all packages, in particular
4531 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08004532 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004533 for (PackageParser.Package pkg : mPackages.values()) {
4534 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004535 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004536 }
4537 }
4538 }
4539
4540 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004541 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004542 }
4543 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004544
Kenny Root447106f2011-03-23 11:00:15 -07004545 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
4546 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004547 if (ps == null) {
4548 return;
4549 }
4550 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08004551 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004552 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 if (replace) {
4555 ps.permissionsFixed = false;
4556 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004557 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 gp.grantedPermissions.clear();
4559 gp.gids = mGlobalGids;
4560 }
4561 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 if (gp.gids == null) {
4564 gp.gids = mGlobalGids;
4565 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 final int N = pkg.requestedPermissions.size();
4568 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07004569 final String name = pkg.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -08004570 //final boolean required = pkg.requestedPermssionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07004571 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004572 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004574 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004577 if (bp != null && bp.packageSetting != null) {
4578 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004580 boolean allowedSig = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004581 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
4582 if (level == PermissionInfo.PROTECTION_NORMAL
4583 || level == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07004585 } else if (bp.packageSetting == null) {
4586 // This permission is invalid; skip it.
4587 allowed = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004588 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Kenny Root447106f2011-03-23 11:00:15 -07004589 allowed = (compareSignatures(
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004590 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 == PackageManager.SIGNATURE_MATCH)
Kenny Root447106f2011-03-23 11:00:15 -07004592 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004593 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborne639da72012-02-21 15:11:13 -08004594 if (!allowed && (bp.protectionLevel
4595 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Kenny Root85387d72010-08-26 10:13:11 -07004596 if (isSystemApp(pkg)) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004597 // For updated system applications, a system permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07004599 if (isUpdatedSystemApp(pkg)) {
Kenny Root447106f2011-03-23 11:00:15 -07004600 final PackageSetting sysPs = mSettings
4601 .getDisabledSystemPkgLPr(pkg.packageName);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004602 final GrantedPermissions origGp = sysPs.sharedUser != null
4603 ? sysPs.sharedUser : sysPs;
4604 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 allowed = true;
4606 } else {
4607 allowed = false;
4608 }
4609 } else {
4610 allowed = true;
4611 }
4612 }
4613 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004614 if (!allowed && (bp.protectionLevel
4615 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
4616 // For development permissions, a development permission
4617 // is granted only if it was already granted.
4618 if (origPermissions.contains(perm)) {
4619 allowed = true;
4620 } else {
4621 allowed = false;
4622 }
4623 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004624 if (allowed) {
4625 allowedSig = true;
4626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 } else {
4628 allowed = false;
4629 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004630 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 if (gp != ps) {
4632 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4633 }
4634 }
4635 if (allowed) {
4636 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4637 && ps.permissionsFixed) {
4638 // If this is an existing, non-system package, then
4639 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004640 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004642 // Except... if this is a permission that was added
4643 // to the platform (note: need to only do this when
4644 // updating the platform).
4645 final int NP = PackageParser.NEW_PERMISSIONS.length;
4646 for (int ip=0; ip<NP; ip++) {
4647 final PackageParser.NewPermissionInfo npi
4648 = PackageParser.NEW_PERMISSIONS[ip];
4649 if (npi.name.equals(perm)
4650 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4651 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004652 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004653 + pkg.packageName);
4654 break;
4655 }
4656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 }
4658 }
4659 if (allowed) {
4660 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004661 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 gp.grantedPermissions.add(perm);
4663 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004664 } else if (!ps.haveGids) {
4665 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 }
4667 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004668 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 + " to package " + pkg.packageName
4670 + " because it was previously installed without");
4671 }
4672 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004673 if (gp.grantedPermissions.remove(perm)) {
4674 changedPermission = true;
4675 gp.gids = removeInts(gp.gids, bp.gids);
4676 Slog.i(TAG, "Un-granting permission " + perm
4677 + " from package " + pkg.packageName
4678 + " (protectionLevel=" + bp.protectionLevel
4679 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4680 + ")");
4681 } else {
4682 Slog.w(TAG, "Not granting permission " + perm
4683 + " to package " + pkg.packageName
4684 + " (protectionLevel=" + bp.protectionLevel
4685 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4686 + ")");
4687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004688 }
4689 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004690 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 + " in package " + pkg.packageName);
4692 }
4693 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004694
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004695 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004696 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4697 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 // This is the first that we have heard about this package, so the
4699 // permissions we have now selected are fixed until explicitly
4700 // changed.
4701 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004703 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004706 private final class ActivityIntentResolver
4707 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004708 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004709 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004710 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004712 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 }
4714
Amith Yamasani483f3b02012-03-13 16:08:00 -07004715 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4716 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004717 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004719 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004720 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004721 }
4722
Kenny Root60f7ad82011-03-22 12:49:06 -07004723 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004724 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004725 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02004726 if (packageActivities == null) {
4727 return null;
4728 }
4729 mFlags = flags;
4730 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004731 final int N = packageActivities.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004732 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4733 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004734
4735 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004736 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004737 intentFilters = packageActivities.get(i).intents;
4738 if (intentFilters != null && intentFilters.size() > 0) {
4739 listCut.add(intentFilters);
4740 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004741 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004742 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02004743 }
4744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004746 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004747 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08004748 if (DEBUG_SHOW_INFO)
4749 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 TAG, " " + type + " " +
4751 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004752 if (DEBUG_SHOW_INFO)
4753 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08004754 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004755 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004757 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4758 intent.setPriority(0);
4759 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4760 + a.className + " with priority > 0, forcing to 0");
4761 }
Kenny Root9718cf52011-02-23 16:45:26 -08004762 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 Log.v(TAG, " IntentFilter:");
4764 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4765 }
4766 if (!intent.debugCheck()) {
4767 Log.w(TAG, "==> For Activity " + a.info.name);
4768 }
4769 addFilter(intent);
4770 }
4771 }
4772
4773 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004774 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004775 if (DEBUG_SHOW_INFO) {
4776 Log.v(TAG, " " + type + " "
4777 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
4778 : a.info.name) + ":");
4779 Log.v(TAG, " Class=" + a.info.name);
4780 }
4781 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004782 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004784 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004785 Log.v(TAG, " IntentFilter:");
4786 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4787 }
4788 removeFilter(intent);
4789 }
4790 }
4791
4792 @Override
4793 protected boolean allowFilterResult(
4794 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4795 ActivityInfo filterAi = filter.activity.info;
4796 for (int i=dest.size()-1; i>=0; i--) {
4797 ActivityInfo destAi = dest.get(i).activityInfo;
4798 if (destAi.name == filterAi.name
4799 && destAi.packageName == filterAi.packageName) {
4800 return false;
4801 }
4802 }
4803 return true;
4804 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07004807 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004808 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004809 PackageParser.Package p = filter.activity.owner;
4810 if (p != null) {
4811 PackageSetting ps = (PackageSetting)p.mExtras;
4812 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004813 // System apps are never considered stopped for purposes of
4814 // filtering, because there may be no way for the user to
4815 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07004816 return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004817 }
4818 }
4819 return false;
4820 }
4821
4822 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004823 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4824 return info.activity.owner.packageName;
4825 }
4826
4827 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004828 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004829 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004830 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004831 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 return null;
4833 }
4834 final PackageParser.Activity activity = info.activity;
4835 if (mSafeMode && (activity.info.applicationInfo.flags
4836 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4837 return null;
4838 }
4839 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07004840 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
4841 res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
4842 ps != null ? ps.getStopped(userId) : false,
4843 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
4844 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4846 res.filter = info;
4847 }
4848 res.priority = info.getPriority();
4849 res.preferredOrder = activity.owner.mPreferredOrder;
4850 //System.out.println("Result: " + res.activityInfo.className +
4851 // " = " + res.priority);
4852 res.match = match;
4853 res.isDefault = info.hasDefault;
4854 res.labelRes = info.labelRes;
4855 res.nonLocalizedLabel = info.nonLocalizedLabel;
4856 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07004857 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 return res;
4859 }
4860
4861 @Override
4862 protected void sortResults(List<ResolveInfo> results) {
4863 Collections.sort(results, mResolvePrioritySorter);
4864 }
4865
4866 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004867 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004868 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004869 out.print(prefix); out.print(
4870 Integer.toHexString(System.identityHashCode(filter.activity)));
4871 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004872 out.print(filter.activity.getComponentShortName());
4873 out.print(" filter ");
4874 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875 }
4876
4877// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4878// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4879// final List<ResolveInfo> retList = Lists.newArrayList();
4880// while (i.hasNext()) {
4881// final ResolveInfo resolveInfo = i.next();
4882// if (isEnabledLP(resolveInfo.activityInfo)) {
4883// retList.add(resolveInfo);
4884// }
4885// }
4886// return retList;
4887// }
4888
4889 // Keys are String (activity class name), values are Activity.
4890 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4891 = new HashMap<ComponentName, PackageParser.Activity>();
4892 private int mFlags;
4893 }
4894
4895 private final class ServiceIntentResolver
4896 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004897 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004898 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004900 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 }
4902
Amith Yamasani483f3b02012-03-13 16:08:00 -07004903 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4904 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004905 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004907 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004908 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 }
4910
Kenny Root60f7ad82011-03-22 12:49:06 -07004911 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004912 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004913 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004914 if (packageServices == null) {
4915 return null;
4916 }
4917 mFlags = flags;
4918 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004919 final int N = packageServices.size();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004920 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4921 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4922
4923 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4924 for (int i = 0; i < N; ++i) {
4925 intentFilters = packageServices.get(i).intents;
4926 if (intentFilters != null && intentFilters.size() > 0) {
4927 listCut.add(intentFilters);
4928 }
4929 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004930 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004931 }
4932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004934 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08004935 if (DEBUG_SHOW_INFO) {
4936 Log.v(TAG, " "
4937 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004938 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004939 Log.v(TAG, " Class=" + s.info.name);
4940 }
4941 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004942 int j;
4943 for (j=0; j<NI; j++) {
4944 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004945 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 Log.v(TAG, " IntentFilter:");
4947 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4948 }
4949 if (!intent.debugCheck()) {
4950 Log.w(TAG, "==> For Service " + s.info.name);
4951 }
4952 addFilter(intent);
4953 }
4954 }
4955
4956 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004957 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004958 if (DEBUG_SHOW_INFO) {
4959 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004960 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004961 Log.v(TAG, " Class=" + s.info.name);
4962 }
4963 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 int j;
4965 for (j=0; j<NI; j++) {
4966 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004967 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 Log.v(TAG, " IntentFilter:");
4969 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4970 }
4971 removeFilter(intent);
4972 }
4973 }
4974
4975 @Override
4976 protected boolean allowFilterResult(
4977 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4978 ServiceInfo filterSi = filter.service.info;
4979 for (int i=dest.size()-1; i>=0; i--) {
4980 ServiceInfo destAi = dest.get(i).serviceInfo;
4981 if (destAi.name == filterSi.name
4982 && destAi.packageName == filterSi.packageName) {
4983 return false;
4984 }
4985 }
4986 return true;
4987 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07004990 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004991 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004992 PackageParser.Package p = filter.service.owner;
4993 if (p != null) {
4994 PackageSetting ps = (PackageSetting)p.mExtras;
4995 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004996 // System apps are never considered stopped for purposes of
4997 // filtering, because there may be no way for the user to
4998 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07004999 return ps.getStopped(userId)
5000 && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08005001 }
5002 }
5003 return false;
5004 }
5005
5006 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005007 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
5008 return info.service.owner.packageName;
5009 }
5010
5011 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005013 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07005014 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06005015 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07005016 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005017 return null;
5018 }
5019 final PackageParser.Service service = info.service;
5020 if (mSafeMode && (service.info.applicationInfo.flags
5021 &ApplicationInfo.FLAG_SYSTEM) == 0) {
5022 return null;
5023 }
5024 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07005025 PackageSetting ps = (PackageSetting) service.owner.mExtras;
5026 res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
5027 ps != null ? ps.getStopped(userId) : false,
5028 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
5029 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
5031 res.filter = filter;
5032 }
5033 res.priority = info.getPriority();
5034 res.preferredOrder = service.owner.mPreferredOrder;
5035 //System.out.println("Result: " + res.activityInfo.className +
5036 // " = " + res.priority);
5037 res.match = match;
5038 res.isDefault = info.hasDefault;
5039 res.labelRes = info.labelRes;
5040 res.nonLocalizedLabel = info.nonLocalizedLabel;
5041 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005042 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005043 return res;
5044 }
5045
5046 @Override
5047 protected void sortResults(List<ResolveInfo> results) {
5048 Collections.sort(results, mResolvePrioritySorter);
5049 }
5050
5051 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005052 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005054 out.print(prefix); out.print(
5055 Integer.toHexString(System.identityHashCode(filter.service)));
5056 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005057 out.print(filter.service.getComponentShortName());
5058 out.print(" filter ");
5059 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005060 }
5061
5062// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
5063// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
5064// final List<ResolveInfo> retList = Lists.newArrayList();
5065// while (i.hasNext()) {
5066// final ResolveInfo resolveInfo = (ResolveInfo) i;
5067// if (isEnabledLP(resolveInfo.serviceInfo)) {
5068// retList.add(resolveInfo);
5069// }
5070// }
5071// return retList;
5072// }
5073
5074 // Keys are String (activity class name), values are Activity.
5075 private final HashMap<ComponentName, PackageParser.Service> mServices
5076 = new HashMap<ComponentName, PackageParser.Service>();
5077 private int mFlags;
5078 };
5079
5080 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
5081 new Comparator<ResolveInfo>() {
5082 public int compare(ResolveInfo r1, ResolveInfo r2) {
5083 int v1 = r1.priority;
5084 int v2 = r2.priority;
5085 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
5086 if (v1 != v2) {
5087 return (v1 > v2) ? -1 : 1;
5088 }
5089 v1 = r1.preferredOrder;
5090 v2 = r2.preferredOrder;
5091 if (v1 != v2) {
5092 return (v1 > v2) ? -1 : 1;
5093 }
5094 if (r1.isDefault != r2.isDefault) {
5095 return r1.isDefault ? -1 : 1;
5096 }
5097 v1 = r1.match;
5098 v2 = r2.match;
5099 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07005100 if (v1 != v2) {
5101 return (v1 > v2) ? -1 : 1;
5102 }
5103 if (r1.system != r2.system) {
5104 return r1.system ? -1 : 1;
5105 }
5106 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 }
5108 };
5109
5110 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
5111 new Comparator<ProviderInfo>() {
5112 public int compare(ProviderInfo p1, ProviderInfo p2) {
5113 final int v1 = p1.initOrder;
5114 final int v2 = p2.initOrder;
5115 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
5116 }
5117 };
5118
Kenny Root447106f2011-03-23 11:00:15 -07005119 static final void sendPackageBroadcast(String action, String pkg,
Amith Yamasani13593602012-03-22 16:16:17 -07005120 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 IActivityManager am = ActivityManagerNative.getDefault();
5122 if (am != null) {
5123 try {
Amith Yamasani13593602012-03-22 16:16:17 -07005124 int[] userIds = userId == UserId.USER_ALL
5125 ? sUserManager.getUserIds()
5126 : new int[] {userId};
5127 for (int id : userIds) {
5128 final Intent intent = new Intent(action,
5129 pkg != null ? Uri.fromParts("package", pkg, null) : null);
5130 if (extras != null) {
5131 intent.putExtras(extras);
5132 }
5133 if (targetPkg != null) {
5134 intent.setPackage(targetPkg);
5135 }
5136 // Modify the UID when posting to other users
5137 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
5138 if (uid > 0 && id > 0) {
5139 uid = UserId.getUid(id, UserId.getAppId(uid));
5140 intent.putExtra(Intent.EXTRA_UID, uid);
5141 }
5142 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
5143 am.broadcastIntent(null, intent, null, finishedReceiver,
5144 0, null, null, null, finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 } catch (RemoteException ex) {
5147 }
5148 }
5149 }
Kenny Root300c13a2011-01-18 13:04:40 -08005150
5151 /**
5152 * Check if the external storage media is available. This is true if there
5153 * is a mounted external storage medium or if the external storage is
5154 * emulated.
5155 */
5156 private boolean isExternalMediaAvailable() {
5157 return mMediaMounted || Environment.isExternalStorageEmulated();
5158 }
5159
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005160 public String nextPackageToClean(String lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07005161 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005162 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005163 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005164 // If the external storage is no longer mounted at this point,
5165 // the caller may not have been able to delete all of this
5166 // packages files and can not delete any more. Bail.
5167 return null;
5168 }
5169 if (lastPackage != null) {
5170 mSettings.mPackagesToBeCleaned.remove(lastPackage);
5171 }
5172 return mSettings.mPackagesToBeCleaned.size() > 0
5173 ? mSettings.mPackagesToBeCleaned.get(0) : null;
5174 }
5175 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005176
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005177 void schedulePackageCleaning(String packageName) {
5178 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
5179 }
5180
5181 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07005182 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005183 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005184 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005185 return;
5186 }
5187 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
5188 return;
5189 }
5190 }
5191 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
5192 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
5193 IActivityManager am = ActivityManagerNative.getDefault();
5194 if (am != null) {
5195 try {
5196 am.startService(null, intent, null);
5197 } catch (RemoteException e) {
5198 }
5199 }
5200 }
5201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 private final class AppDirObserver extends FileObserver {
5203 public AppDirObserver(String path, int mask, boolean isrom) {
5204 super(path, mask);
5205 mRootDir = path;
5206 mIsRom = isrom;
5207 }
5208
5209 public void onEvent(int event, String path) {
5210 String removedPackage = null;
5211 int removedUid = -1;
5212 String addedPackage = null;
5213 int addedUid = -1;
5214
Kenny Root447106f2011-03-23 11:00:15 -07005215 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 synchronized (mInstallLock) {
5217 String fullPathStr = null;
5218 File fullPath = null;
5219 if (path != null) {
5220 fullPath = new File(mRootDir, path);
5221 fullPathStr = fullPath.getPath();
5222 }
5223
Kenny Root9718cf52011-02-23 16:45:26 -08005224 if (DEBUG_APP_DIR_OBSERVER)
5225 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226
5227 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08005228 if (DEBUG_APP_DIR_OBSERVER)
5229 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 return;
5231 }
5232
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005233 // Ignore packages that are being installed or
5234 // have just been installed.
5235 if (ignoreCodePath(fullPathStr)) {
5236 return;
5237 }
5238 PackageParser.Package p = null;
Kenny Root447106f2011-03-23 11:00:15 -07005239 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005240 synchronized (mPackages) {
5241 p = mAppDirs.get(fullPathStr);
5242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005244 if (p != null) {
5245 removePackageLI(p, true);
5246 removedPackage = p.applicationInfo.packageName;
5247 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005248 }
5249 }
5250
5251 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005253 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07005254 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
5255 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 PackageParser.PARSE_CHATTY |
5257 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005258 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
5259 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005261 /*
5262 * TODO this seems dangerous as the package may have
5263 * changed since we last acquired the mPackages
5264 * lock.
5265 */
5266 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005268 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08005269 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 }
5271 addedPackage = p.applicationInfo.packageName;
5272 addedUid = p.applicationInfo.uid;
5273 }
5274 }
5275 }
5276
Kenny Root447106f2011-03-23 11:00:15 -07005277 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005279 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 }
5281 }
5282
5283 if (removedPackage != null) {
5284 Bundle extras = new Bundle(1);
5285 extras.putInt(Intent.EXTRA_UID, removedUid);
5286 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005287 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005288 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 }
5290 if (addedPackage != null) {
5291 Bundle extras = new Bundle(1);
5292 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005293 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005294 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296 }
5297
5298 private final String mRootDir;
5299 private final boolean mIsRom;
5300 }
Jacek Surazski65e13172009-04-28 15:26:38 +02005301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 /* Called when a downloaded package installation has been confirmed by the user */
5303 public void installPackage(
5304 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02005305 installPackage(packageURI, observer, flags, null);
5306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005307
Jacek Surazski65e13172009-04-28 15:26:38 +02005308 /* Called when a downloaded package installation has been confirmed by the user */
5309 public void installPackage(
5310 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
5311 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07005312 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005313 null, null);
Kenny Root5ab21572011-07-27 11:11:19 -07005314 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005315
Kenny Root5ab21572011-07-27 11:11:19 -07005316 @Override
5317 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
5318 int flags, String installerPackageName, Uri verificationURI,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005319 ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
Kenny Root5ab21572011-07-27 11:11:19 -07005320 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
5321
5322 final int uid = Binder.getCallingUid();
5323
5324 final int filteredFlags;
5325
5326 if (uid == Process.SHELL_UID || uid == 0) {
5327 if (DEBUG_INSTALL) {
5328 Slog.v(TAG, "Install from ADB");
5329 }
5330 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
5331 } else {
5332 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
5333 }
5334
5335 final Message msg = mHandler.obtainMessage(INIT_COPY);
5336 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005337 verificationURI, manifestDigest, encryptionParams);
Kenny Root5ab21572011-07-27 11:11:19 -07005338 mHandler.sendMessage(msg);
5339 }
5340
5341 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07005342 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
Kenny Root5ab21572011-07-27 11:11:19 -07005343 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07005344 final PackageVerificationResponse response = new PackageVerificationResponse(
5345 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07005346 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07005347 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005348 mHandler.sendMessage(msg);
5349 }
5350
Kenny Root05ca4c92011-09-15 10:36:25 -07005351 private ComponentName matchComponentForVerifier(String packageName,
5352 List<ResolveInfo> receivers) {
5353 ActivityInfo targetReceiver = null;
5354
5355 final int NR = receivers.size();
5356 for (int i = 0; i < NR; i++) {
5357 final ResolveInfo info = receivers.get(i);
5358 if (info.activityInfo == null) {
5359 continue;
5360 }
5361
5362 if (packageName.equals(info.activityInfo.packageName)) {
5363 targetReceiver = info.activityInfo;
5364 break;
5365 }
5366 }
5367
5368 if (targetReceiver == null) {
5369 return null;
5370 }
5371
5372 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
5373 }
5374
5375 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
5376 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
5377 if (pkgInfo.verifiers.length == 0) {
5378 return null;
5379 }
5380
5381 final int N = pkgInfo.verifiers.length;
5382 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
5383 for (int i = 0; i < N; i++) {
5384 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
5385
5386 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
5387 receivers);
5388 if (comp == null) {
5389 continue;
5390 }
5391
5392 final int verifierUid = getUidForVerifier(verifierInfo);
5393 if (verifierUid == -1) {
5394 continue;
5395 }
5396
5397 if (DEBUG_VERIFY) {
5398 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
5399 + " with the correct signature");
5400 }
5401 sufficientVerifiers.add(comp);
5402 verificationState.addSufficientVerifier(verifierUid);
5403 }
5404
5405 return sufficientVerifiers;
5406 }
5407
5408 private int getUidForVerifier(VerifierInfo verifierInfo) {
5409 synchronized (mPackages) {
5410 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
5411 if (pkg == null) {
5412 return -1;
5413 } else if (pkg.mSignatures.length != 1) {
5414 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5415 + " has more than one signature; ignoring");
5416 return -1;
5417 }
5418
5419 /*
5420 * If the public key of the package's signature does not match
5421 * our expected public key, then this is a different package and
5422 * we should skip.
5423 */
5424
5425 final byte[] expectedPublicKey;
5426 try {
5427 final Signature verifierSig = pkg.mSignatures[0];
5428 final PublicKey publicKey = verifierSig.getPublicKey();
5429 expectedPublicKey = publicKey.getEncoded();
5430 } catch (CertificateException e) {
5431 return -1;
5432 }
5433
5434 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
5435
5436 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
5437 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5438 + " does not have the expected public key; ignoring");
5439 return -1;
5440 }
5441
5442 return pkg.applicationInfo.uid;
5443 }
5444 }
5445
Christopher Tate1bb69062010-02-19 17:02:12 -08005446 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07005447 enforceSystemOrRoot("Only the system is allowed to finish installs");
5448
5449 if (DEBUG_INSTALL) {
5450 Slog.v(TAG, "BM finishing package install for " + token);
5451 }
5452
5453 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08005454 mHandler.sendMessage(msg);
5455 }
5456
Kenny Root5ab21572011-07-27 11:11:19 -07005457 /**
5458 * Get the verification agent timeout.
5459 *
5460 * @return verification timeout in milliseconds
5461 */
5462 private long getVerificationTimeout() {
5463 return android.provider.Settings.Secure.getLong(mContext.getContentResolver(),
5464 android.provider.Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
5465 DEFAULT_VERIFICATION_TIMEOUT);
5466 }
5467
5468 /**
rich canningsa6cfe522012-05-21 15:50:56 -07005469 * Get the default verification agent response code.
5470 *
5471 * @return default verification response code
5472 */
5473 private int getDefaultVerificationResponse() {
5474 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5475 android.provider.Settings.Secure.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
5476 DEFAULT_VERIFICATION_RESPONSE);
5477 }
5478
5479 /**
Kenny Root5ab21572011-07-27 11:11:19 -07005480 * Check whether or not package verification has been enabled.
5481 *
5482 * @return true if verification should be performed
5483 */
5484 private boolean isVerificationEnabled() {
5485 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5486 android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
5487 DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
5488 }
5489
Matt Finifterf8a98ed2012-05-14 15:43:34 -07005490 /**
5491 * Get the "allow unknown sources" setting.
5492 *
5493 * @return the current "allow unknown sources" setting
5494 */
5495 private int getUnknownSourcesSettings() {
5496 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5497 android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
5498 -1);
5499 }
5500
Kenny Rootf03b45f2011-02-23 17:25:45 -08005501 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08005502 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07005503 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08005504 synchronized (mPackages) {
5505 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
5506 if (targetPackageSetting == null) {
5507 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
5508 }
5509
5510 PackageSetting installerPackageSetting;
5511 if (installerPackageName != null) {
5512 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
5513 if (installerPackageSetting == null) {
5514 throw new IllegalArgumentException("Unknown installer package: "
5515 + installerPackageName);
5516 }
5517 } else {
5518 installerPackageSetting = null;
5519 }
5520
5521 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07005522 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08005523 if (obj != null) {
5524 if (obj instanceof SharedUserSetting) {
5525 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
5526 } else if (obj instanceof PackageSetting) {
5527 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
5528 } else {
5529 throw new SecurityException("Bad object " + obj + " for uid " + uid);
5530 }
5531 } else {
5532 throw new SecurityException("Unknown calling uid " + uid);
5533 }
5534
5535 // Verify: can't set installerPackageName to a package that is
5536 // not signed with the same cert as the caller.
5537 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005538 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005539 installerPackageSetting.signatures.mSignatures)
5540 != PackageManager.SIGNATURE_MATCH) {
5541 throw new SecurityException(
5542 "Caller does not have same cert as new installer package "
5543 + installerPackageName);
5544 }
5545 }
5546
5547 // Verify: if target already has an installer package, it must
5548 // be signed with the same cert as the caller.
5549 if (targetPackageSetting.installerPackageName != null) {
5550 PackageSetting setting = mSettings.mPackages.get(
5551 targetPackageSetting.installerPackageName);
5552 // If the currently set package isn't valid, then it's always
5553 // okay to change it.
5554 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005555 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005556 setting.signatures.mSignatures)
5557 != PackageManager.SIGNATURE_MATCH) {
5558 throw new SecurityException(
5559 "Caller does not have same cert as old installer package "
5560 + targetPackageSetting.installerPackageName);
5561 }
5562 }
5563 }
5564
5565 // Okay!
5566 targetPackageSetting.installerPackageName = installerPackageName;
5567 scheduleWriteSettingsLocked();
5568 }
5569 }
5570
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005571 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005572 // Queue up an async operation since the package installation may take a little while.
5573 mHandler.post(new Runnable() {
5574 public void run() {
5575 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005576 // Result object to be returned
5577 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005578 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005579 res.uid = -1;
5580 res.pkg = null;
5581 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005582 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005583 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005584 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005585 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005586 }
Kenny Root6dceb882012-04-12 14:23:49 -07005587 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005588 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005589
5590 // A restore should be performed at this point if (a) the install
5591 // succeeded, (b) the operation is not an update, and (c) the new
5592 // package has a backupAgent defined.
5593 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08005594 boolean doRestore = (!update
5595 && res.pkg != null
5596 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08005597
5598 // Set up the post-install work request bookkeeping. This will be used
5599 // and cleaned up by the post-install event handling regardless of whether
5600 // there's a restore pass performed. Token values are >= 1.
5601 int token;
5602 if (mNextInstallToken < 0) mNextInstallToken = 1;
5603 token = mNextInstallToken++;
5604
5605 PostInstallData data = new PostInstallData(args, res);
5606 mRunningInstalls.put(token, data);
5607 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
5608
5609 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
5610 // Pass responsibility to the Backup Manager. It will perform a
5611 // restore if appropriate, then pass responsibility back to the
5612 // Package Manager to run the post-install observer callbacks
5613 // and broadcasts.
5614 IBackupManager bm = IBackupManager.Stub.asInterface(
5615 ServiceManager.getService(Context.BACKUP_SERVICE));
5616 if (bm != null) {
5617 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
5618 + " to BM for possible restore");
5619 try {
5620 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
5621 } catch (RemoteException e) {
5622 // can't happen; the backup manager is local
5623 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005624 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08005625 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005626 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005627 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005628 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08005629 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005632
5633 if (!doRestore) {
5634 // No restore possible, or the Backup Manager was mysteriously not
5635 // available -- just fire the post-install work request directly.
5636 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
5637 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
5638 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 }
5641 });
5642 }
5643
Kenny Root5ab21572011-07-27 11:11:19 -07005644 private abstract class HandlerParams {
5645 private static final int MAX_RETRIES = 4;
5646
5647 /**
5648 * Number of times startCopy() has been attempted and had a non-fatal
5649 * error.
5650 */
5651 private int mRetries = 0;
5652
Dianne Hackborn7d608422011-08-07 16:24:18 -07005653 final boolean startCopy() {
5654 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005655 try {
Kenny Root5ab21572011-07-27 11:11:19 -07005656 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
5657
5658 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005659 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005660 mHandler.sendEmptyMessage(MCS_GIVE_UP);
5661 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005662 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005663 } else {
5664 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005665 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005666 }
5667 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07005668 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005669 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005670 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005671 }
5672 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005673 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005674 }
5675
5676 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07005677 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005678 handleServiceError();
5679 handleReturnCode();
5680 }
Kenny Root5ab21572011-07-27 11:11:19 -07005681
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005682 abstract void handleStartCopy() throws RemoteException;
5683 abstract void handleServiceError();
5684 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005685 }
5686
Kenny Root366949c2011-01-14 17:18:14 -08005687 class MeasureParams extends HandlerParams {
5688 private final PackageStats mStats;
5689 private boolean mSuccess;
5690
5691 private final IPackageStatsObserver mObserver;
5692
Kenny Roota69b7eb2012-05-14 14:47:06 -07005693 public MeasureParams(PackageStats stats, IPackageStatsObserver observer) {
Kenny Root366949c2011-01-14 17:18:14 -08005694 mObserver = observer;
5695 mStats = stats;
Kenny Root366949c2011-01-14 17:18:14 -08005696 }
5697
5698 @Override
5699 void handleStartCopy() throws RemoteException {
Kenny Roota69b7eb2012-05-14 14:47:06 -07005700 synchronized (mInstallLock) {
5701 mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats);
5702 }
Kenny Root366949c2011-01-14 17:18:14 -08005703
Kenny Roota69b7eb2012-05-14 14:47:06 -07005704 final boolean mounted;
Kenny Root366949c2011-01-14 17:18:14 -08005705 if (Environment.isExternalStorageEmulated()) {
5706 mounted = true;
5707 } else {
5708 final String status = Environment.getExternalStorageState();
5709
5710 mounted = status.equals(Environment.MEDIA_MOUNTED)
5711 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
5712 }
5713
5714 if (mounted) {
5715 final File externalCacheDir = Environment
5716 .getExternalStorageAppCacheDirectory(mStats.packageName);
5717 final long externalCacheSize = mContainerService
5718 .calculateDirectorySize(externalCacheDir.getPath());
5719 mStats.externalCacheSize = externalCacheSize;
5720
5721 final File externalDataDir = Environment
5722 .getExternalStorageAppDataDirectory(mStats.packageName);
5723 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
5724 .getPath());
5725
5726 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
5727 externalDataSize -= externalCacheSize;
5728 }
5729 mStats.externalDataSize = externalDataSize;
5730
5731 final File externalMediaDir = Environment
5732 .getExternalStorageAppMediaDirectory(mStats.packageName);
5733 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08005734 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08005735
5736 final File externalObbDir = Environment
5737 .getExternalStorageAppObbDirectory(mStats.packageName);
5738 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
5739 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08005740 }
5741 }
5742
5743 @Override
5744 void handleReturnCode() {
5745 if (mObserver != null) {
5746 try {
5747 mObserver.onGetStatsCompleted(mStats, mSuccess);
5748 } catch (RemoteException e) {
5749 Slog.i(TAG, "Observer no longer exists.");
5750 }
5751 }
5752 }
5753
5754 @Override
5755 void handleServiceError() {
5756 Slog.e(TAG, "Could not measure application " + mStats.packageName
5757 + " external storage");
5758 }
5759 }
5760
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005761 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005762 final IPackageInstallObserver observer;
5763 int flags;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005764
5765 private final Uri mPackageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005766 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005767 final Uri verificationURI;
5768 final ManifestDigest manifestDigest;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005769 private InstallArgs mArgs;
5770 private int mRet;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005771 private File mTempPackage;
5772 final ContainerEncryptionParams encryptionParams;
Kenny Root5ab21572011-07-27 11:11:19 -07005773
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005774 InstallParams(Uri packageURI,
5775 IPackageInstallObserver observer, int flags,
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005776 String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
5777 ContainerEncryptionParams encryptionParams) {
5778 this.mPackageURI = packageURI;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005779 this.flags = flags;
5780 this.observer = observer;
5781 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005782 this.verificationURI = verificationURI;
5783 this.manifestDigest = manifestDigest;
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005784 this.encryptionParams = encryptionParams;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005785 }
5786
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005787 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
5788 String packageName = pkgLite.packageName;
5789 int installLocation = pkgLite.installLocation;
5790 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07005791 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005792 synchronized (mPackages) {
5793 PackageParser.Package pkg = mPackages.get(packageName);
5794 if (pkg != null) {
5795 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5796 // Check for updated system application.
5797 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5798 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005799 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005800 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
5801 }
5802 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5803 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005804 if (onSd) {
5805 // Install flag overrides everything.
5806 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5807 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005808 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005809 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
5810 // Application explicitly specified internal.
5811 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5812 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
5813 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005814 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005815 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07005816 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005817 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5818 }
5819 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005820 }
5821 }
5822 } else {
5823 // Invalid install. Return error code
5824 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
5825 }
5826 }
5827 }
5828 // All the special cases have been taken care of.
5829 // Return result based on recommended install location.
5830 if (onSd) {
5831 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5832 }
5833 return pkgLite.recommendedInstallLocation;
5834 }
5835
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005836 /*
5837 * Invoke remote method to get package information and install
5838 * location values. Override install location based on default
5839 * policy if needed and then create install arguments based
5840 * on the install location.
5841 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005842 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08005843 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07005844 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
5845 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
5846 PackageInfoLite pkgLite = null;
5847
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005848 if (onInt && onSd) {
5849 // Check if both bits are set.
5850 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
5851 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005852 } else {
Kenny Root62e1b4e2011-03-14 17:13:39 -07005853 final long lowThreshold;
5854
5855 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
5856 .getService(DeviceStorageMonitorService.SERVICE);
5857 if (dsm == null) {
5858 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
5859 lowThreshold = 0L;
5860 } else {
5861 lowThreshold = dsm.getMemoryLowThreshold();
5862 }
5863
Kenny Root11128572010-10-11 10:51:32 -07005864 try {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005865 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
Kenny Root11128572010-10-11 10:51:32 -07005866 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root11128572010-10-11 10:51:32 -07005867
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005868 final File packageFile;
5869 if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
5870 ParcelFileDescriptor out = null;
5871
5872 mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
5873 if (mTempPackage != null) {
5874 try {
5875 out = ParcelFileDescriptor.open(mTempPackage,
5876 ParcelFileDescriptor.MODE_READ_WRITE);
5877 } catch (FileNotFoundException e) {
5878 Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
5879 }
5880
5881 // Make a temporary file for decryption.
5882 ret = mContainerService
5883 .copyResource(mPackageURI, encryptionParams, out);
5884
5885 packageFile = mTempPackage;
5886
5887 FileUtils.setPermissions(packageFile.getAbsolutePath(),
5888 FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IROTH,
5889 -1, -1);
5890 } else {
5891 packageFile = null;
5892 }
5893 } else {
5894 packageFile = new File(mPackageURI.getPath());
5895 }
5896
5897 if (packageFile != null) {
5898 // Remote call to find out default install location
5899 pkgLite = mContainerService.getMinimalPackageInfo(
5900 packageFile.getAbsolutePath(), flags, lowThreshold);
5901 }
5902 } finally {
5903 mContext.revokeUriPermission(mPackageURI,
5904 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5905 }
5906 }
5907
5908 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005909 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005910 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005911 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005912 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005913 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005914 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005915 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5916 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
5917 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005918 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
5919 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005920 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07005921 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005922 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005923 // Override with defaults if needed.
5924 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005925 if (!onSd && !onInt) {
5926 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005927 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
5928 // Set the flag to install on external media.
5929 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005930 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005931 } else {
5932 // Make sure the flag for installing on external
5933 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005934 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005935 flags &= ~PackageManager.INSTALL_EXTERNAL;
5936 }
5937 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005938 }
5939 }
Kenny Root5ab21572011-07-27 11:11:19 -07005940
5941 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07005942 mArgs = args;
5943
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005944 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Kenny Root5ab21572011-07-27 11:11:19 -07005945 /*
5946 * Determine if we have any installed package verifiers. If we
5947 * do, then we'll defer to them to verify the packages.
5948 */
Kenny Root05ca4c92011-09-15 10:36:25 -07005949 final int requiredUid = mRequiredVerifierPackage == null ? -1
Amith Yamasani483f3b02012-03-13 16:08:00 -07005950 : getPackageUid(mRequiredVerifierPackage, 0);
Kenny Root05ca4c92011-09-15 10:36:25 -07005951 if (requiredUid != -1 && isVerificationEnabled()) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07005952 final Intent verification = new Intent(
5953 Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
5954 verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07005955 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07005956
Kenny Root05ca4c92011-09-15 10:36:25 -07005957 final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005958 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07005959
5960 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07005961 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07005962 + verification.toString() + " with " + pkgLite.verifiers.length
5963 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07005964 }
5965
5966 final int verificationId = mPendingVerificationToken++;
5967
5968 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
5969
5970 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
5971 installerPackageName);
5972
5973 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
5974
5975 if (verificationURI != null) {
5976 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
5977 verificationURI);
5978 }
5979
Kenny Root05ca4c92011-09-15 10:36:25 -07005980 final PackageVerificationState verificationState = new PackageVerificationState(
5981 requiredUid, args);
5982
5983 mPendingVerification.append(verificationId, verificationState);
5984
5985 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
5986 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07005987
5988 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07005989 * If any sufficient verifiers were listed in the package
5990 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07005991 */
Kenny Root05ca4c92011-09-15 10:36:25 -07005992 if (sufficientVerifiers != null) {
5993 final int N = sufficientVerifiers.size();
5994 if (N == 0) {
5995 Slog.i(TAG, "Additional verifiers required, but none installed.");
5996 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
5997 } else {
5998 for (int i = 0; i < N; i++) {
5999 final ComponentName verifierComponent = sufficientVerifiers.get(i);
6000
6001 final Intent sufficientIntent = new Intent(verification);
6002 sufficientIntent.setComponent(verifierComponent);
6003
6004 mContext.sendBroadcast(sufficientIntent);
6005 }
6006 }
6007 }
6008
6009 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
6010 mRequiredVerifierPackage, receivers);
6011 if (ret == PackageManager.INSTALL_SUCCEEDED
6012 && mRequiredVerifierPackage != null) {
6013 /*
6014 * Send the intent to the required verification agent,
6015 * but only start the verification timeout after the
6016 * target BroadcastReceivers have run.
6017 */
6018 verification.setComponent(requiredVerifierComponent);
6019 mContext.sendOrderedBroadcast(verification,
6020 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
6021 new BroadcastReceiver() {
6022 @Override
6023 public void onReceive(Context context, Intent intent) {
6024 final Message msg = mHandler
6025 .obtainMessage(CHECK_PENDING_VERIFICATION);
6026 msg.arg1 = verificationId;
6027 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
6028 }
6029 }, null, 0, null, null);
6030
6031 /*
6032 * We don't want the copy to proceed until verification
6033 * succeeds, so null out this field.
6034 */
6035 mArgs = null;
6036 }
Kenny Root5ab21572011-07-27 11:11:19 -07006037 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07006038 /*
6039 * No package verification is enabled, so immediately start
6040 * the remote call to initiate copy using temporary file.
6041 */
Kenny Root5ab21572011-07-27 11:11:19 -07006042 ret = args.copyApk(mContainerService, true);
6043 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006044 }
Kenny Root5ab21572011-07-27 11:11:19 -07006045
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006046 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006047 }
6048
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006049 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006050 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07006051 // If mArgs is null, then MCS couldn't be reached. When it
6052 // reconnects, it will try again to install. At that point, this
6053 // will succeed.
6054 if (mArgs != null) {
6055 processPendingInstall(mArgs, mRet);
6056 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006057
6058 if (mTempPackage != null) {
6059 if (!mTempPackage.delete()) {
6060 Slog.w(TAG, "Couldn't delete temporary file: "
6061 + mTempPackage.getAbsolutePath());
6062 }
6063 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006064 }
6065
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006066 @Override
6067 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006068 mArgs = createInstallArgs(this);
6069 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006070 }
Kenny Root6dceb882012-04-12 14:23:49 -07006071
6072 public boolean isForwardLocked() {
6073 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6074 }
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006075
6076 public Uri getPackageUri() {
6077 if (mTempPackage != null) {
6078 return Uri.fromFile(mTempPackage);
6079 } else {
6080 return mPackageURI;
6081 }
6082 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006083 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006084
6085 /*
6086 * Utility class used in movePackage api.
6087 * srcArgs and targetArgs are not set for invalid flags and make
6088 * sure to do null checks when invoking methods on them.
6089 * We probably want to return ErrorPrams for both failed installs
6090 * and moves.
6091 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006092 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006093 final IPackageMoveObserver observer;
6094 final int flags;
6095 final String packageName;
6096 final InstallArgs srcArgs;
6097 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07006098 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006099 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07006100
6101 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Kenny Root6dceb882012-04-12 14:23:49 -07006102 String packageName, String dataDir, int uid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006103 this.srcArgs = srcArgs;
6104 this.observer = observer;
6105 this.flags = flags;
6106 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07006107 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006108 if (srcArgs != null) {
6109 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07006110 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006111 } else {
6112 targetArgs = null;
6113 }
6114 }
6115
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006116 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006117 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6118 // Check for storage space on target medium
6119 if (!targetArgs.checkFreeStorage(mContainerService)) {
6120 Log.w(TAG, "Insufficient storage to install");
6121 return;
6122 }
Kenny Rootbf023582012-05-02 16:56:15 -07006123
6124 mRet = srcArgs.doPreCopy();
6125 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6126 return;
6127 }
6128
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006129 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07006130 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6131 srcArgs.doPostCopy(uid);
6132 return;
6133 }
6134
6135 mRet = srcArgs.doPostCopy(uid);
6136 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6137 return;
6138 }
6139
6140 mRet = targetArgs.doPreInstall(mRet);
6141 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
6142 return;
6143 }
6144
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006145 if (DEBUG_SD_INSTALL) {
6146 StringBuilder builder = new StringBuilder();
6147 if (srcArgs != null) {
6148 builder.append("src: ");
6149 builder.append(srcArgs.getCodePath());
6150 }
6151 if (targetArgs != null) {
6152 builder.append(" target : ");
6153 builder.append(targetArgs.getCodePath());
6154 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006155 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006156 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006157 }
6158
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006159 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006160 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07006161 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006162 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
6163 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
6164 currentStatus = PackageManager.MOVE_SUCCEEDED;
6165 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
6166 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
6167 }
6168 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006169 }
6170
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006171 @Override
6172 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006173 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006174 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006175 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006176
Kenny Root6dceb882012-04-12 14:23:49 -07006177 /**
6178 * Used during creation of InstallArgs
6179 *
6180 * @param flags package installation flags
6181 * @return true if should be installed on external storage
6182 */
6183 private static boolean installOnSd(int flags) {
6184 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
6185 return false;
6186 }
6187 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
6188 return true;
6189 }
6190 return false;
6191 }
6192
6193 /**
6194 * Used during creation of InstallArgs
6195 *
6196 * @param flags package installation flags
6197 * @return true if should be installed as forward locked
6198 */
6199 private static boolean installForwardLocked(int flags) {
6200 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6201 }
6202
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006203 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07006204 if (installOnSd(params.flags) || params.isForwardLocked()) {
6205 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006206 } else {
6207 return new FileInstallArgs(params);
6208 }
6209 }
6210
Kenny Root85387d72010-08-26 10:13:11 -07006211 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
6212 String nativeLibraryPath) {
Kenny Root84e35ea2012-06-06 16:05:05 -07006213 final boolean isInAsec;
6214 if (installOnSd(flags)) {
6215 /* Apps on SD card are always in ASEC containers. */
6216 isInAsec = true;
6217 } else if (installForwardLocked(flags)
6218 && !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
6219 /*
6220 * Forward-locked apps are only in ASEC containers if they're the
6221 * new style
6222 */
6223 isInAsec = true;
6224 } else {
6225 isInAsec = false;
6226 }
6227
6228 if (isInAsec) {
Kenny Root6dceb882012-04-12 14:23:49 -07006229 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006230 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006231 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006232 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006233 }
6234 }
6235
Kenny Root85387d72010-08-26 10:13:11 -07006236 // Used by package mover
6237 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07006238 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07006239 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
6240 + AsecInstallArgs.RES_FILE_NAME);
6241 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
6242 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006243 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006244 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006245 }
6246 }
6247
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006248 static abstract class InstallArgs {
6249 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006250 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006251 final int flags;
6252 final Uri packageURI;
6253 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006254 final ManifestDigest manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006255
Kenny Root5ab21572011-07-27 11:11:19 -07006256 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
6257 String installerPackageName, ManifestDigest manifestDigest) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006258 this.packageURI = packageURI;
6259 this.flags = flags;
6260 this.observer = observer;
6261 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07006262 this.manifestDigest = manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006263 }
6264
6265 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006266 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006267 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006268 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07006269
6270 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006271 abstract String getCodePath();
6272 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07006273 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006274 // Need installer lock especially for dex file removal.
6275 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006276 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006277 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07006278
Kenny Rootbf023582012-05-02 16:56:15 -07006279 /**
6280 * Called before the source arguments are copied. This is used mostly
6281 * for MoveParams when it needs to read the source file to put it in the
6282 * destination.
6283 */
6284 int doPreCopy() {
6285 return PackageManager.INSTALL_SUCCEEDED;
6286 }
6287
6288 /**
6289 * Called after the source arguments are copied. This is used mostly for
6290 * MoveParams when it needs to read the source file to put it in the
6291 * destination.
6292 *
6293 * @return
6294 */
6295 int doPostCopy(int uid) {
6296 return PackageManager.INSTALL_SUCCEEDED;
6297 }
6298
Kenny Root6dceb882012-04-12 14:23:49 -07006299 protected boolean isFwdLocked() {
6300 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6301 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006302 }
6303
6304 class FileInstallArgs extends InstallArgs {
6305 File installDir;
6306 String codeFileName;
6307 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07006308 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006309 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006310
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006311 FileInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006312 super(params.getPackageUri(), params.observer, params.flags,
6313 params.installerPackageName, params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006314 }
6315
Kenny Root85387d72010-08-26 10:13:11 -07006316 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Kenny Root5ab21572011-07-27 11:11:19 -07006317 super(null, null, 0, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006318 File codeFile = new File(fullCodePath);
6319 installDir = codeFile.getParentFile();
6320 codeFileName = fullCodePath;
6321 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006322 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006323 }
6324
Kenny Root85387d72010-08-26 10:13:11 -07006325 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Kenny Root5ab21572011-07-27 11:11:19 -07006326 super(packageURI, null, 0, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07006327 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006328 String apkName = getNextCodePath(null, pkgName, ".apk");
6329 codeFileName = new File(installDir, apkName + ".apk").getPath();
6330 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07006331 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006332 }
6333
Kenny Root11128572010-10-11 10:51:32 -07006334 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07006335 final long lowThreshold;
6336
6337 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
6338 .getService(DeviceStorageMonitorService.SERVICE);
6339 if (dsm == null) {
6340 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
6341 lowThreshold = 0L;
6342 } else {
6343 if (dsm.isMemoryLow()) {
6344 Log.w(TAG, "Memory is reported as being too low; aborting package install");
6345 return false;
6346 }
6347
6348 lowThreshold = dsm.getMemoryLowThreshold();
6349 }
6350
Kenny Root11128572010-10-11 10:51:32 -07006351 try {
6352 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6353 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006354 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07006355 } finally {
6356 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6357 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006358 }
6359
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006360 String getCodePath() {
6361 return codeFileName;
6362 }
6363
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006364 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07006365 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006366 codeFileName = createTempPackageFile(installDir).getPath();
6367 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006368 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006369 }
6370
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006371 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006372 if (temp) {
6373 // Generate temp file name
6374 createCopyFile();
6375 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006376 // Get a ParcelFileDescriptor to write to the output file
6377 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006378 if (!created) {
6379 try {
6380 codeFile.createNewFile();
6381 // Set permissions
6382 if (!setPermissions()) {
6383 // Failed setting permissions.
6384 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6385 }
6386 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006387 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006388 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6389 }
6390 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006391 ParcelFileDescriptor out = null;
6392 try {
Kenny Root85387d72010-08-26 10:13:11 -07006393 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006394 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07006395 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006396 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6397 }
6398 // Copy the resource now
6399 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6400 try {
Kenny Root11128572010-10-11 10:51:32 -07006401 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6402 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006403 ret = imcs.copyResource(packageURI, null, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006404 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07006405 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07006406 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006407 }
Kenny Root85387d72010-08-26 10:13:11 -07006408
Kenny Root2782a472012-04-14 21:48:21 -07006409 if (isFwdLocked()) {
6410 final File destResourceFile = new File(getResourcePath());
6411
6412 // Copy the public files
6413 try {
6414 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
6415 } catch (IOException e) {
6416 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
6417 + " forward-locked app.");
6418 destResourceFile.delete();
6419 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6420 }
6421 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006422 return ret;
6423 }
6424
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006425 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006426 if (status != PackageManager.INSTALL_SUCCEEDED) {
6427 cleanUp();
6428 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006429 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006430 }
6431
6432 boolean doRename(int status, final String pkgName, String oldCodePath) {
6433 if (status != PackageManager.INSTALL_SUCCEEDED) {
6434 cleanUp();
6435 return false;
6436 } else {
Kenny Root2782a472012-04-14 21:48:21 -07006437 final File oldCodeFile = new File(getCodePath());
6438 final File oldResourceFile = new File(getResourcePath());
6439
6440 // Rename APK file based on packageName
6441 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
6442 final File newCodeFile = new File(installDir, apkName + ".apk");
6443 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006444 return false;
6445 }
Kenny Root2782a472012-04-14 21:48:21 -07006446 codeFileName = newCodeFile.getPath();
6447
6448 // Rename public resource file if it's forward-locked.
6449 final File newResFile = new File(getResourcePathFromCodePath());
6450 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
6451 return false;
6452 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006453 resourceFileName = getResourcePathFromCodePath();
Kenny Root2782a472012-04-14 21:48:21 -07006454
6455 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006456 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006457 return false;
6458 }
Kenny Root2782a472012-04-14 21:48:21 -07006459
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006460 return true;
6461 }
6462 }
6463
Kenny Root6dceb882012-04-12 14:23:49 -07006464 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006465 if (status != PackageManager.INSTALL_SUCCEEDED) {
6466 cleanUp();
6467 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006468 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006469 }
6470
6471 String getResourcePath() {
6472 return resourceFileName;
6473 }
6474
Kenny Root2782a472012-04-14 21:48:21 -07006475 private String getResourcePathFromCodePath() {
6476 final String codePath = getCodePath();
6477 if (isFwdLocked()) {
6478 final StringBuilder sb = new StringBuilder();
6479
6480 sb.append(mAppInstallDir.getPath());
6481 sb.append('/');
6482 sb.append(getApkName(codePath));
6483 sb.append(".zip");
6484
6485 /*
6486 * If our APK is a temporary file, mark the resource as a
6487 * temporary file as well so it can be cleaned up after
6488 * catastrophic failure.
6489 */
6490 if (codePath.endsWith(".tmp")) {
6491 sb.append(".tmp");
6492 }
6493
6494 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006495 } else {
6496 return codePath;
6497 }
6498 }
6499
Kenny Root85387d72010-08-26 10:13:11 -07006500 @Override
6501 String getNativeLibraryPath() {
6502 return libraryPath;
6503 }
6504
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006505 private boolean cleanUp() {
6506 boolean ret = true;
6507 String sourceDir = getCodePath();
6508 String publicSourceDir = getResourcePath();
6509 if (sourceDir != null) {
6510 File sourceFile = new File(sourceDir);
6511 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006512 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006513 ret = false;
6514 }
6515 // Delete application's code and resources
6516 sourceFile.delete();
6517 }
6518 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
6519 final File publicSourceFile = new File(publicSourceDir);
6520 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006521 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006522 }
6523 if (publicSourceFile.exists()) {
6524 publicSourceFile.delete();
6525 }
6526 }
6527 return ret;
6528 }
6529
6530 void cleanUpResourcesLI() {
6531 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006532 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006533 int retCode = mInstaller.rmdex(sourceDir);
6534 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006535 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006536 + " at location "
6537 + sourceDir + ", retcode=" + retCode);
6538 // we don't consider this to be a failure of the core package deletion
6539 }
6540 }
6541 }
6542
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006543 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006544 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07006545 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006546 final int filePermissions =
6547 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
6548 |FileUtils.S_IROTH;
6549 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
6550 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006551 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006552 getCodePath()
6553 + ". The return code was: " + retCode);
6554 // TODO Define new internal error
6555 return false;
6556 }
6557 return true;
6558 }
6559 return true;
6560 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006561
6562 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07006563 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006564 cleanUpResourcesLI();
6565 return true;
6566 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006567 }
6568
Kenny Root51a573c2012-05-17 13:30:28 -07006569 private boolean isAsecExternal(String cid) {
6570 final String asecPath = PackageHelper.getSdFilesystem(cid);
6571 return !asecPath.startsWith(mAsecInternalPath);
6572 }
6573
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07006574 /**
6575 * Extract the MountService "container ID" from the full code path of an
6576 * .apk.
6577 */
6578 static String cidFromCodePath(String fullCodePath) {
6579 int eidx = fullCodePath.lastIndexOf("/");
6580 String subStr1 = fullCodePath.substring(0, eidx);
6581 int sidx = subStr1.lastIndexOf("/");
6582 return subStr1.substring(sidx+1, eidx);
6583 }
6584
Kenny Root6dceb882012-04-12 14:23:49 -07006585 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006586 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07006587 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006588
Kenny Root85387d72010-08-26 10:13:11 -07006589 String cid;
6590 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07006591 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006592 String libraryPath;
6593
Kenny Root6dceb882012-04-12 14:23:49 -07006594 AsecInstallArgs(InstallParams params) {
Anonymous Cowardceb1b0b2012-04-24 10:35:16 -07006595 super(params.getPackageUri(), params.observer, params.flags,
6596 params.installerPackageName, params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006597 }
6598
Kenny Root6dceb882012-04-12 14:23:49 -07006599 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006600 boolean isExternal, boolean isForwardLocked) {
6601 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6602 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006603 // Extract cid from fullCodePath
6604 int eidx = fullCodePath.lastIndexOf("/");
6605 String subStr1 = fullCodePath.substring(0, eidx);
6606 int sidx = subStr1.lastIndexOf("/");
6607 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07006608 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006609 }
6610
Kenny Rootc7a89992012-06-05 15:13:17 -07006611 AsecInstallArgs(String cid, boolean isForwardLocked) {
6612 super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
6613 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07006614 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07006615 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006616 }
6617
Kenny Rootbf023582012-05-02 16:56:15 -07006618 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
6619 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6620 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006621 this.cid = cid;
6622 }
6623
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006624 void createCopyFile() {
6625 cid = getTempContainerId();
6626 }
6627
Kenny Root11128572010-10-11 10:51:32 -07006628 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
6629 try {
6630 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6631 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006632 return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07006633 } finally {
6634 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6635 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006636 }
6637
Kenny Root6dceb882012-04-12 14:23:49 -07006638 private final boolean isExternal() {
6639 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
6640 }
6641
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006642 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006643 if (temp) {
6644 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07006645 } else {
6646 /*
6647 * Pre-emptively destroy the container since it's destroyed if
6648 * copying fails due to it existing anyway.
6649 */
6650 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006651 }
Kenny Root11128572010-10-11 10:51:32 -07006652
6653 final String newCachePath;
6654 try {
6655 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6656 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006657 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
6658 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07006659 } finally {
6660 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6661 }
6662
Kenny Root85387d72010-08-26 10:13:11 -07006663 if (newCachePath != null) {
6664 setCachePath(newCachePath);
6665 return PackageManager.INSTALL_SUCCEEDED;
6666 } else {
6667 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6668 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006669 }
6670
6671 @Override
6672 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07006673 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006674 }
6675
6676 @Override
6677 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07006678 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006679 }
6680
6681 @Override
6682 String getNativeLibraryPath() {
6683 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006684 }
6685
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006686 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006687 if (status != PackageManager.INSTALL_SUCCEEDED) {
6688 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006689 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006690 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006691 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006692 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07006693 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
6694 Process.SYSTEM_UID);
6695 if (newCachePath != null) {
6696 setCachePath(newCachePath);
6697 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006698 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6699 }
6700 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006701 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006702 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006703 }
6704
6705 boolean doRename(int status, final String pkgName,
6706 String oldCodePath) {
6707 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006708 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006709 if (PackageHelper.isContainerMounted(cid)) {
6710 // Unmount the container
6711 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006712 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006713 return false;
6714 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006715 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006716 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07006717 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
6718 " which might be stale. Will try to clean up.");
6719 // Clean up the stale container and proceed to recreate.
6720 if (!PackageHelper.destroySdDir(newCacheId)) {
6721 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
6722 return false;
6723 }
6724 // Successfully cleaned up stale container. Try to rename again.
6725 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
6726 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
6727 + " inspite of cleaning it up.");
6728 return false;
6729 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006730 }
6731 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006732 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006733 newCachePath = PackageHelper.mountSdDir(newCacheId,
6734 getEncryptKey(), Process.SYSTEM_UID);
6735 } else {
6736 newCachePath = PackageHelper.getSdDir(newCacheId);
6737 }
6738 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006739 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006740 return false;
6741 }
6742 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07006743 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006744 " at new path: " + newCachePath);
6745 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07006746 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006747 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006748 }
6749
Kenny Root85387d72010-08-26 10:13:11 -07006750 private void setCachePath(String newCachePath) {
6751 File cachePath = new File(newCachePath);
6752 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
6753 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07006754
6755 if (isFwdLocked()) {
6756 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
6757 } else {
6758 resourcePath = packagePath;
6759 }
Kenny Root85387d72010-08-26 10:13:11 -07006760 }
6761
Kenny Root6dceb882012-04-12 14:23:49 -07006762 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006763 if (status != PackageManager.INSTALL_SUCCEEDED) {
6764 cleanUp();
6765 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07006766 final int groupOwner;
6767 final String protectedFile;
6768 if (isFwdLocked()) {
6769 groupOwner = uid;
6770 protectedFile = RES_FILE_NAME;
6771 } else {
6772 groupOwner = -1;
6773 protectedFile = null;
6774 }
6775
Kenny Root6dceb882012-04-12 14:23:49 -07006776 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07006777 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07006778 Slog.e(TAG, "Failed to finalize " + cid);
6779 PackageHelper.destroySdDir(cid);
6780 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6781 }
6782
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006783 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006784 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07006785 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006786 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006787 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006788 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006789 }
6790
6791 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07006792 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
6793
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006794 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006795 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006796 }
6797
6798 void cleanUpResourcesLI() {
6799 String sourceFile = getCodePath();
6800 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006801 int retCode = mInstaller.rmdex(sourceFile);
6802 if (retCode < 0) {
6803 Slog.w(TAG, "Couldn't remove dex file for package: "
6804 + " at location "
6805 + sourceFile.toString() + ", retcode=" + retCode);
6806 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006807 }
6808 cleanUp();
6809 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006810
6811 boolean matchContainer(String app) {
6812 if (cid.startsWith(app)) {
6813 return true;
6814 }
6815 return false;
6816 }
6817
6818 String getPackageName() {
Kenny Rootc7a89992012-06-05 15:13:17 -07006819 return getAsecPackageName(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006820 }
6821
6822 boolean doPostDeleteLI(boolean delete) {
6823 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006824 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006825 if (mounted) {
6826 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006827 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006828 }
6829 if (ret && delete) {
6830 cleanUpResourcesLI();
6831 }
6832 return ret;
6833 }
Kenny Rootbf023582012-05-02 16:56:15 -07006834
6835 @Override
6836 int doPreCopy() {
6837 if (isFwdLocked()) {
6838 if (!PackageHelper.fixSdPermissions(cid,
6839 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
6840 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6841 }
6842 }
6843
6844 return PackageManager.INSTALL_SUCCEEDED;
6845 }
6846
6847 @Override
6848 int doPostCopy(int uid) {
6849 if (isFwdLocked()) {
Kenny Rootbf023582012-05-02 16:56:15 -07006850 if (uid < Process.FIRST_APPLICATION_UID
6851 || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) {
6852 Slog.e(TAG, "Failed to finalize " + cid);
6853 PackageHelper.destroySdDir(cid);
6854 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6855 }
6856 }
6857
6858 return PackageManager.INSTALL_SUCCEEDED;
6859 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006860 };
6861
Kenny Rootc7a89992012-06-05 15:13:17 -07006862 static String getAsecPackageName(String packageCid) {
6863 int idx = packageCid.lastIndexOf("-");
6864 if (idx == -1) {
6865 return packageCid;
6866 }
6867 return packageCid.substring(0, idx);
6868 }
6869
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006870 // Utility method used to create code paths based on package name and available index.
6871 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
6872 String idxStr = "";
6873 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006874 // Fall back to default value of idx=1 if prefix is not
6875 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006876 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006877 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006878 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006879 if (subStr.endsWith(suffix)) {
6880 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006881 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006882 // If oldCodePath already contains prefix find out the
6883 // ending index to either increment or decrement.
6884 int sidx = subStr.lastIndexOf(prefix);
6885 if (sidx != -1) {
6886 subStr = subStr.substring(sidx + prefix.length());
6887 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006888 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
6889 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006890 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006891 try {
6892 idx = Integer.parseInt(subStr);
6893 if (idx <= 1) {
6894 idx++;
6895 } else {
6896 idx--;
6897 }
6898 } catch(NumberFormatException e) {
6899 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006900 }
6901 }
6902 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006903 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006904 return prefix + idxStr;
6905 }
6906
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006907 // Utility method used to ignore ADD/REMOVE events
6908 // by directory observer.
6909 private static boolean ignoreCodePath(String fullPathStr) {
6910 String apkName = getApkName(fullPathStr);
6911 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
6912 if (idx != -1 && ((idx+1) < apkName.length())) {
6913 // Make sure the package ends with a numeral
6914 String version = apkName.substring(idx+1);
6915 try {
6916 Integer.parseInt(version);
6917 return true;
6918 } catch (NumberFormatException e) {}
6919 }
6920 return false;
6921 }
6922
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006923 // Utility method that returns the relative package path with respect
6924 // to the installation directory. Like say for /data/data/com.test-1.apk
6925 // string com.test-1 is returned.
6926 static String getApkName(String codePath) {
6927 if (codePath == null) {
6928 return null;
6929 }
6930 int sidx = codePath.lastIndexOf("/");
6931 int eidx = codePath.lastIndexOf(".");
6932 if (eidx == -1) {
6933 eidx = codePath.length();
6934 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006935 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006936 return null;
6937 }
6938 return codePath.substring(sidx+1, eidx);
6939 }
6940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 class PackageInstalledInfo {
6942 String name;
6943 int uid;
6944 PackageParser.Package pkg;
6945 int returnCode;
6946 PackageRemovedInfo removedInfo;
6947 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 /*
6950 * Install a non-existing package.
6951 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006952 private void installNewPackageLI(PackageParser.Package pkg,
6953 int parseFlags,
6954 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006955 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006956 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006957 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08006958
Amith Yamasani0b285492011-04-14 17:35:23 -07006959 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006960 res.name = pkgName;
6961 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07006962 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
6963 // A package with the same name is already installed, though
6964 // it has been renamed to an older name. The package we
6965 // are trying to install should be installed as an update to
6966 // the existing one, but that has not been requested, so bail.
6967 Slog.w(TAG, "Attempt to re-install " + pkgName
6968 + " without first uninstalling package running as "
6969 + mSettings.mRenamedPackages.get(pkgName));
6970 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6971 return;
6972 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006973 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006975 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 + " without first uninstalling.");
6977 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6978 return;
6979 }
6980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006981 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006982 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
6983 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006985 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006986 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
6987 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
6988 }
6989 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006990 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02006991 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006992 res);
6993 // delete the partially installed application. the data directory will have to be
6994 // restored if it was already existing
6995 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
6996 // remove package from internal structures. Note that we want deletePackageX to
6997 // delete the package data and cache directories that it created in
6998 // scanPackageLocked, unless those directories existed before we even tried to
6999 // install.
7000 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007001 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007002 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007003 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 }
7005 }
7006 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007007
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007008 private void replacePackageLI(PackageParser.Package pkg,
7009 int parseFlags,
7010 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007011 String installerPackageName, PackageInstalledInfo res) {
7012
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007013 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007014 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007015 // First find the old package info and check signatures
7016 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007017 oldPackage = mPackages.get(pkgName);
Kenny Root447106f2011-03-23 11:00:15 -07007018 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07007019 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07007020 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
7022 return;
7023 }
7024 }
Kenny Root85387d72010-08-26 10:13:11 -07007025 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007026 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007027 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007028 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007029 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 }
7031 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007033 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007034 PackageParser.Package pkg,
7035 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007036 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 PackageParser.Package newPackage = null;
7038 String pkgName = deletedPackage.packageName;
7039 boolean deletedPkg = true;
7040 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007041
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007042 long origUpdateTime;
7043 if (pkg.mExtras != null) {
7044 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
7045 } else {
7046 origUpdateTime = 0;
7047 }
7048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007050 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007051 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007052 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7054 deletedPkg = false;
7055 } else {
7056 // Successfully deleted the old package. Now proceed with re-installation
7057 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007058 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
7059 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007060 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007061 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7063 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08007064 }
7065 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007066 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007067 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 res);
7069 updatedSettings = true;
7070 }
7071 }
7072
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007073 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007074 // remove package from internal structures. Note that we want deletePackageX to
7075 // delete the package data and cache directories that it created in
7076 // scanPackageLocked, unless those directories existed before we even tried to
7077 // install.
7078 if(updatedSettings) {
7079 deletePackageLI(
7080 pkgName, true,
7081 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007082 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007083 }
7084 // Since we failed to install the new package we need to restore the old
7085 // package that we deleted.
7086 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007087 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007088 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007089 boolean oldOnSd = isExternal(deletedPackage);
7090 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
7091 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
7092 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007093 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
7094 | SCAN_UPDATE_TIME;
7095 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
7096 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007097 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
7098 return;
7099 }
7100 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07007101 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007102 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007103 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007104 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07007105 // can downgrade to reader
7106 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007107 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007108 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 }
7110 }
7111 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007113 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007114 PackageParser.Package pkg,
7115 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02007116 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 PackageParser.Package newPackage = null;
7118 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007119 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 PackageParser.PARSE_IS_SYSTEM;
7121 String packageName = deletedPackage.packageName;
7122 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
7123 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007124 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125 return;
7126 }
7127 PackageParser.Package oldPkg;
7128 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07007129 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 synchronized (mPackages) {
7131 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007132 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007133 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
7134 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007135 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007136 return;
7137 }
7138 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007139
7140 killApplication(packageName, oldPkg.applicationInfo.uid);
7141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 res.removedInfo.uid = oldPkg.applicationInfo.uid;
7143 res.removedInfo.removedPackage = packageName;
7144 // Remove existing system package
7145 removePackageLI(oldPkg, true);
Kenny Root447106f2011-03-23 11:00:15 -07007146 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007147 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007148 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007149 // We didn't need to disable the .apk as a current system package,
7150 // which means we are replacing another update that is already
7151 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07007152 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007153 deletedPackage.applicationInfo.sourceDir,
7154 deletedPackage.applicationInfo.publicSourceDir,
7155 deletedPackage.applicationInfo.nativeLibraryDir);
7156 } else {
7157 res.removedInfo.args = null;
7158 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08007159 }
7160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 // Successfully disabled the old package. Now proceed with re-installation
7162 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
7163 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007164 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007166 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
7168 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
7169 }
7170 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007171 if (newPackage.mExtras != null) {
7172 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
7173 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
7174 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
7175 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007176 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 updatedSettings = true;
7178 }
7179
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007180 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007181 // Re installation failed. Restore old information
7182 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07007183 if (newPackage != null) {
7184 removePackageLI(newPackage, true);
7185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007187 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 // Restore the old system information in Settings
7189 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007190 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007191 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02007192 mSettings.setInstallerPackageName(packageName,
7193 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007194 }
Kenny Root447106f2011-03-23 11:00:15 -07007195 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007196 }
7197 }
7198 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007199
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007200 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007201 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007202 int retCode;
7203 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
7204 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
7205 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07007206 if (mNoDexOpt) {
7207 /*
7208 * If we're in an engineering build, programs are lazily run
7209 * through dexopt. If the .dex file doesn't exist yet, it
7210 * will be created when the program is run next.
7211 */
7212 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
7213 } else {
7214 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
7215 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7216 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007217 }
7218 }
7219 return PackageManager.INSTALL_SUCCEEDED;
7220 }
7221
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007222 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02007223 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007224 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 synchronized (mPackages) {
7226 //write settings. the installStatus will be incomplete at this stage.
7227 //note that the new package setting would have already been
7228 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007229 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07007230 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007231 }
7232
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07007233 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007234 != PackageManager.INSTALL_SUCCEEDED) {
7235 // Discontinue if moving dex files failed.
7236 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 }
Kenny Root6dceb882012-04-12 14:23:49 -07007238
7239 Log.d(TAG, "New package installed in " + newPackage.mPath);
7240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007242 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08007243 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
7244 ? UPDATE_PERMISSIONS_ALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 res.name = pkgName;
7246 res.uid = newPackage.applicationInfo.uid;
7247 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07007248 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02007249 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7251 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07007252 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 }
7254 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007255
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007256 private void installPackageLI(InstallArgs args,
7257 boolean newInstall, PackageInstalledInfo res) {
7258 int pFlags = args.flags;
7259 String installerPackageName = args.installerPackageName;
7260 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007261 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08007262 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007263 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007264 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007265 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07007266 // Result object to be returned
7267 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
7268
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007269 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07007270 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
7271 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
7272 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007273 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
7274 pp.setSeparateProcesses(mSeparateProcesses);
7275 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
7276 null, mMetrics, parseFlags);
7277 if (pkg == null) {
7278 res.returnCode = pp.getParseError();
7279 return;
7280 }
7281 String pkgName = res.name = pkg.packageName;
7282 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
7283 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
7284 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
7285 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007286 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007287 }
7288 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
7289 res.returnCode = pp.getParseError();
7290 return;
7291 }
Kenny Root5ab21572011-07-27 11:11:19 -07007292
7293 /* If the installer passed in a manifest digest, compare it now. */
7294 if (args.manifestDigest != null) {
7295 if (DEBUG_INSTALL) {
7296 final String parsedManifest = pkg.manifestDigest == null ? "null"
7297 : pkg.manifestDigest.toString();
7298 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
7299 + parsedManifest);
7300 }
7301
7302 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
7303 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
7304 return;
7305 }
7306 } else if (DEBUG_INSTALL) {
7307 final String parsedManifest = pkg.manifestDigest == null
7308 ? "null" : pkg.manifestDigest.toString();
7309 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
7310 }
7311
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007312 // Get rid of all references to package scan path via parser.
7313 pp = null;
7314 String oldCodePath = null;
7315 boolean systemApp = false;
7316 synchronized (mPackages) {
7317 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007318 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
7319 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08007320 if (pkg.mOriginalPackages != null
7321 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007322 && mPackages.containsKey(oldName)) {
7323 // This package is derived from an original package,
7324 // and this device has been updating from that original
7325 // name. We must continue using the original name, so
7326 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08007327 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007328 pkgName = pkg.packageName;
7329 replace = true;
7330 } else if (mPackages.containsKey(pkgName)) {
7331 // This package, under its official name, already exists
7332 // on the device; we should replace it.
7333 replace = true;
7334 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007335 }
7336 PackageSetting ps = mSettings.mPackages.get(pkgName);
7337 if (ps != null) {
7338 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
7339 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
7340 systemApp = (ps.pkg.applicationInfo.flags &
7341 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07007342 }
7343 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007344 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007345
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007346 if (systemApp && onSd) {
7347 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007348 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007349 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
7350 return;
7351 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08007352
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007353 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
7354 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7355 return;
7356 }
7357 // Set application objects path explicitly after the rename
7358 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07007359 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007360 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007361 replacePackageLI(pkg, parseFlags, scanMode,
7362 installerPackageName, res);
7363 } else {
7364 installNewPackageLI(pkg, parseFlags, scanMode,
7365 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 }
7367 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007368
Kenny Root85387d72010-08-26 10:13:11 -07007369 private static boolean isForwardLocked(PackageParser.Package pkg) {
7370 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 }
7372
Kenny Root88670d82012-05-09 15:47:35 -07007373
7374 private boolean isForwardLocked(PackageSetting ps) {
7375 return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
7376 }
7377
Kenny Root85387d72010-08-26 10:13:11 -07007378 private static boolean isExternal(PackageParser.Package pkg) {
7379 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7380 }
7381
Kenny Root6dceb882012-04-12 14:23:49 -07007382 private static boolean isExternal(PackageSetting ps) {
7383 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7384 }
7385
Kenny Root85387d72010-08-26 10:13:11 -07007386 private static boolean isSystemApp(PackageParser.Package pkg) {
7387 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7388 }
7389
Kenny Root502e9a42011-01-10 13:48:15 -08007390 private static boolean isSystemApp(ApplicationInfo info) {
7391 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7392 }
7393
Kenny Root208d3412012-05-07 19:42:35 -07007394 private static boolean isSystemApp(PackageSetting ps) {
7395 return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
7396 }
7397
Kenny Root85387d72010-08-26 10:13:11 -07007398 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
7399 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007400 }
7401
Kenny Root88670d82012-05-09 15:47:35 -07007402 private int packageFlagsToInstallFlags(PackageSetting ps) {
7403 int installFlags = 0;
7404 if (isExternal(ps)) {
7405 installFlags |= PackageManager.INSTALL_EXTERNAL;
7406 }
7407 if (isForwardLocked(ps)) {
7408 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
7409 }
7410 return installFlags;
7411 }
7412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 private void deleteTempPackageFiles() {
7414 FilenameFilter filter = new FilenameFilter() {
7415 public boolean accept(File dir, String name) {
7416 return name.startsWith("vmdl") && name.endsWith(".tmp");
7417 }
7418 };
7419 String tmpFilesList[] = mAppInstallDir.list(filter);
7420 if(tmpFilesList == null) {
7421 return;
7422 }
7423 for(int i = 0; i < tmpFilesList.length; i++) {
7424 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
7425 tmpFile.delete();
7426 }
7427 }
7428
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007429 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007430 File tmpPackageFile;
7431 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007432 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007434 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007435 return null;
7436 }
7437 try {
7438 FileUtils.setPermissions(
7439 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
7440 -1, -1);
7441 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007442 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 return null;
7444 }
7445 return tmpPackageFile;
7446 }
7447
7448 public void deletePackage(final String packageName,
7449 final IPackageDeleteObserver observer,
7450 final int flags) {
7451 mContext.enforceCallingOrSelfPermission(
7452 android.Manifest.permission.DELETE_PACKAGES, null);
7453 // Queue up an async operation since the package deletion may take a little while.
7454 mHandler.post(new Runnable() {
7455 public void run() {
7456 mHandler.removeCallbacks(this);
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007457 final int returnCode = deletePackageX(packageName, true, true, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007458 if (observer != null) {
7459 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007460 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 } catch (RemoteException e) {
7462 Log.i(TAG, "Observer no longer exists.");
7463 } //end catch
7464 } //end if
7465 } //end run
7466 });
7467 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007469 /**
7470 * This method is an internal method that could be get invoked either
7471 * to delete an installed package or to clean up a failed installation.
7472 * After deleting an installed package, a broadcast is sent to notify any
7473 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007474 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 * installation wouldn't have sent the initial broadcast either
7476 * The key steps in deleting a package are
7477 * deleting the package information in internal structures like mPackages,
7478 * deleting the packages base directories through installd
7479 * updating mSettings to reflect current status
7480 * persisting settings for later use
7481 * sending a broadcast if necessary
7482 */
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007483 private int deletePackageX(String packageName, boolean sendBroadCast,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 boolean deleteCodeAndResources, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007485 final PackageRemovedInfo info = new PackageRemovedInfo();
7486 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007488 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
7489 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
7490 try {
7491 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007492 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007493 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007494 }
7495 } catch (RemoteException e) {
7496 }
7497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007499 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007500 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007501 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007502
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007503 if (res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07007504 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007505 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07007506
7507 // If the removed package was a system update, the old system packaged
7508 // was re-enabled; we need to broadcast this information
7509 if (systemUpdate) {
7510 Bundle extras = new Bundle(1);
7511 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
7512 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7513
Dianne Hackborne7f97212011-02-24 14:40:20 -08007514 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007515 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007516 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007517 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007518 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Amith Yamasani13593602012-03-22 16:16:17 -07007519 null, packageName, null, UserId.USER_ALL);
Romain Guy96f43572009-03-24 20:27:49 -07007520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007521 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007522 // Force a gc here.
7523 Runtime.getRuntime().gc();
7524 // Delete the resources here after sending the broadcast to let
7525 // other processes clean up before deleting resources.
7526 if (info.args != null) {
7527 synchronized (mInstallLock) {
7528 info.args.doPostDeleteLI(deleteCodeAndResources);
7529 }
7530 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007531
7532 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 }
7534
7535 static class PackageRemovedInfo {
7536 String removedPackage;
7537 int uid = -1;
7538 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07007539 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007540 // Clean up resources deleted packages.
7541 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07007542
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007543 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 Bundle extras = new Bundle(1);
7545 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
7546 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
7547 if (replacing) {
7548 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7549 }
7550 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08007551 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007552 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007553 if (fullRemove && !replacing) {
7554 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007555 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557 }
7558 if (removedUid >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07007559 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
7560 UserId.getUserId(removedUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 }
7562 }
7563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 /*
7566 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
7567 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007568 * 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 -08007569 * delete a partially installed application.
7570 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007571 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007572 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007574 if (outInfo != null) {
7575 outInfo.removedPackage = packageName;
7576 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007577 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07007579 final PackageSetting deletedPs;
7580 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 synchronized (mPackages) {
7582 deletedPs = mSettings.mPackages.get(packageName);
7583 }
7584 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007585 int retCode = mInstaller.remove(packageName, 0);
7586 if (retCode < 0) {
7587 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
7588 + packageName + ", retcode=" + retCode);
7589 // we don't consider this to be a failure of the core package deletion
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 } else {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007591 // TODO: Kill the processes first
Amith Yamasani13593602012-03-22 16:16:17 -07007592 sUserManager.removePackageForAllUsers(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007593 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07007594 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 }
Kenny Root447106f2011-03-23 11:00:15 -07007596 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007598 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007599 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
7600 if (outInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007601 outInfo.removedUid = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007602 }
7603 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007604 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007605 if (deletedPs.sharedUser != null) {
7606 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07007607 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007608 }
7609 }
Dianne Hackborn04505102012-02-29 12:34:04 -08007610 clearPackagePreferredActivitiesLPw(deletedPs.name);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007611 }
7612 }
Kenny Root447106f2011-03-23 11:00:15 -07007613 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007614 if (writeSettings) {
7615 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07007616 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 }
7619 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007621 /*
7622 * Tries to delete system package.
7623 */
7624 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007625 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 ApplicationInfo applicationInfo = p.applicationInfo;
7627 //applicable for non-partially installed applications only
7628 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007629 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630 return false;
7631 }
7632 PackageSetting ps = null;
7633 // Confirm if the system package has been updated
7634 // An updated system app can be deleted. This will also have to restore
7635 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07007636 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007638 ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007639 }
7640 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007641 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 return false;
7643 } else {
7644 Log.i(TAG, "Deleting system pkg from data partition");
7645 }
7646 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07007647 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007648 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007649 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007650 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007651 } else {
7652 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007653 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007654 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007655 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007656 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 if (!ret) {
7658 return false;
7659 }
Kenny Root447106f2011-03-23 11:00:15 -07007660 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007661 synchronized (mPackages) {
7662 // Reinstate the old system package
Kenny Root447106f2011-03-23 11:00:15 -07007663 mSettings.enableSystemPackageLPw(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07007664 // Remove any native libraries from the upgraded package.
7665 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007666 }
7667 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007668 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007670 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007672 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007673 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007674 return false;
7675 }
Kenny Root447106f2011-03-23 11:00:15 -07007676 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007678 updatePermissionsLPw(newPkg.packageName, newPkg,
7679 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Kenny Root447106f2011-03-23 11:00:15 -07007680 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007681 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007682 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007684 }
7685 return true;
7686 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007688 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007689 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7690 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007691 ApplicationInfo applicationInfo = p.applicationInfo;
7692 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007693 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 return false;
7695 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007696 if (outInfo != null) {
7697 outInfo.uid = applicationInfo.uid;
7698 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699
7700 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007701 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702
7703 // Delete application code and resources
7704 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007705 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07007706 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
7707 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
7708 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
7709 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007710 }
7711 return true;
7712 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007714 /*
7715 * This method handles package deletion in general
7716 */
7717 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007718 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7719 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007721 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 return false;
7723 }
7724 PackageParser.Package p;
7725 boolean dataOnly = false;
7726 synchronized (mPackages) {
7727 p = mPackages.get(packageName);
7728 if (p == null) {
7729 //this retrieves partially installed apps
7730 dataOnly = true;
7731 PackageSetting ps = mSettings.mPackages.get(packageName);
7732 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007733 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 return false;
7735 }
7736 p = ps.pkg;
7737 }
7738 }
7739 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007740 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 return false;
7742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 if (dataOnly) {
7745 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007746 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007747 return true;
7748 }
7749 // At this point the package should have ApplicationInfo associated with it
7750 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007751 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 return false;
7753 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007754 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07007755 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007756 Log.i(TAG, "Removing system package:"+p.packageName);
7757 // When an updated system application is deleted we delete the existing resources as well and
7758 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007759 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007760 } else {
7761 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007762 // Kill application pre-emptively especially for apps on sd.
7763 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007764 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
7765 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007767 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007769
Amith Yamasani483f3b02012-03-13 16:08:00 -07007770 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007771 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07007772 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 mContext.enforceCallingOrSelfPermission(
7774 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasani483f3b02012-03-13 16:08:00 -07007775 checkValidCaller(Binder.getCallingUid(), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007776 // Queue up an async operation since the package deletion may take a little while.
7777 mHandler.post(new Runnable() {
7778 public void run() {
7779 mHandler.removeCallbacks(this);
7780 final boolean succeeded;
7781 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007782 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 }
7784 if (succeeded) {
7785 // invoke DeviceStorageMonitor's update method to clear any notifications
7786 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
7787 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
7788 if (dsm != null) {
7789 dsm.updateMemory();
7790 }
7791 }
7792 if(observer != null) {
7793 try {
7794 observer.onRemoveCompleted(packageName, succeeded);
7795 } catch (RemoteException e) {
7796 Log.i(TAG, "Observer no longer exists.");
7797 }
7798 } //end if observer
7799 } //end run
7800 });
7801 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007802
Amith Yamasani483f3b02012-03-13 16:08:00 -07007803 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007805 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007806 return false;
7807 }
7808 PackageParser.Package p;
7809 boolean dataOnly = false;
7810 synchronized (mPackages) {
7811 p = mPackages.get(packageName);
7812 if(p == null) {
7813 dataOnly = true;
7814 PackageSetting ps = mSettings.mPackages.get(packageName);
7815 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007816 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 return false;
7818 }
7819 p = ps.pkg;
7820 }
7821 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08007822
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08007823 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007824 //need to check this only for fully installed applications
7825 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007826 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 return false;
7828 }
7829 final ApplicationInfo applicationInfo = p.applicationInfo;
7830 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007831 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 return false;
7833 }
7834 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007835 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007836 if (retCode < 0) {
7837 Slog.w(TAG, "Couldn't remove cache files for package: "
7838 + packageName);
7839 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 }
7841 return true;
7842 }
7843
7844 public void deleteApplicationCacheFiles(final String packageName,
7845 final IPackageDataObserver observer) {
7846 mContext.enforceCallingOrSelfPermission(
7847 android.Manifest.permission.DELETE_CACHE_FILES, null);
7848 // Queue up an async operation since the package deletion may take a little while.
Amith Yamasani483f3b02012-03-13 16:08:00 -07007849 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007850 mHandler.post(new Runnable() {
7851 public void run() {
7852 mHandler.removeCallbacks(this);
7853 final boolean succeded;
7854 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007855 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 }
7857 if(observer != null) {
7858 try {
7859 observer.onRemoveCompleted(packageName, succeded);
7860 } catch (RemoteException e) {
7861 Log.i(TAG, "Observer no longer exists.");
7862 }
7863 } //end if observer
7864 } //end run
7865 });
7866 }
7867
Amith Yamasani483f3b02012-03-13 16:08:00 -07007868 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007869 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007870 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 return false;
7872 }
7873 PackageParser.Package p;
7874 synchronized (mPackages) {
7875 p = mPackages.get(packageName);
7876 }
7877 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007878 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007879 return false;
7880 }
7881 final ApplicationInfo applicationInfo = p.applicationInfo;
7882 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007883 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007884 return false;
7885 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007886 // TODO: Pass userId to deleteCacheFiles
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007887 int retCode = mInstaller.deleteCacheFiles(packageName);
7888 if (retCode < 0) {
7889 Slog.w(TAG, "Couldn't remove cache files for package: "
7890 + packageName);
7891 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007892 }
7893 return true;
7894 }
7895
7896 public void getPackageSizeInfo(final String packageName,
7897 final IPackageStatsObserver observer) {
7898 mContext.enforceCallingOrSelfPermission(
7899 android.Manifest.permission.GET_PACKAGE_SIZE, null);
Kenny Root366949c2011-01-14 17:18:14 -08007900
Kenny Roota69b7eb2012-05-14 14:47:06 -07007901 PackageStats stats = new PackageStats(packageName);
Kenny Root366949c2011-01-14 17:18:14 -08007902
Kenny Roota69b7eb2012-05-14 14:47:06 -07007903 /*
7904 * Queue up an async operation since the package measurement may take a
7905 * little while.
7906 */
7907 Message msg = mHandler.obtainMessage(INIT_COPY);
7908 msg.obj = new MeasureParams(stats, observer);
7909 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 }
7911
7912 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
7913 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007914 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 return false;
7916 }
7917 PackageParser.Package p;
7918 boolean dataOnly = false;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007919 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920 synchronized (mPackages) {
7921 p = mPackages.get(packageName);
7922 if(p == null) {
7923 dataOnly = true;
7924 PackageSetting ps = mSettings.mPackages.get(packageName);
7925 if((ps == null) || (ps.pkg == 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 p = ps.pkg;
7930 }
Kenny Root2afded12012-06-04 16:39:47 -07007931 if (p != null && (isExternal(p) || isForwardLocked(p))) {
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007932 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
7933 if (secureContainerId != null) {
7934 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
7935 }
7936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 }
7938 String publicSrcDir = null;
7939 if(!dataOnly) {
7940 final ApplicationInfo applicationInfo = p.applicationInfo;
7941 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007942 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 return false;
7944 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007945 if (isForwardLocked(p)) {
7946 publicSrcDir = applicationInfo.publicSourceDir;
7947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007949 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
7950 asecPath, pStats);
7951 if (res < 0) {
7952 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007953 }
Kenny Root2afded12012-06-04 16:39:47 -07007954
7955 // Fix-up for forward-locked applications in ASEC containers.
7956 if (!isExternal(p)) {
7957 pStats.codeSize += pStats.externalCodeSize;
7958 pStats.externalCodeSize = 0L;
7959 }
7960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007961 return true;
7962 }
7963
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07007966 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 }
7968
7969 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07007970 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 }
7972
7973 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007974 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975 }
7976
Kenny Root447106f2011-03-23 11:00:15 -07007977 private int getUidTargetSdkVersionLockedLPr(int uid) {
7978 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007979 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07007980 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007981 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07007982 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007983 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07007984 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007985 if (ps.pkg != null) {
7986 int v = ps.pkg.applicationInfo.targetSdkVersion;
7987 if (v < vers) vers = v;
7988 }
7989 }
7990 return vers;
7991 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07007992 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007993 if (ps.pkg != null) {
7994 return ps.pkg.applicationInfo.targetSdkVersion;
7995 }
7996 }
7997 return Build.VERSION_CODES.CUR_DEVELOPMENT;
7998 }
7999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008000 public void addPreferredActivity(IntentFilter filter, int match,
8001 ComponentName[] set, ComponentName activity) {
Kenny Root447106f2011-03-23 11:00:15 -07008002 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008004 if (mContext.checkCallingOrSelfPermission(
8005 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8006 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008007 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008008 < Build.VERSION_CODES.FROYO) {
8009 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
8010 + Binder.getCallingUid());
8011 return;
8012 }
8013 mContext.enforceCallingOrSelfPermission(
8014 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8015 }
8016
8017 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
8019 mSettings.mPreferredActivities.addFilter(
8020 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008021 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 }
8023 }
8024
Satish Sampath8dbe6122009-06-02 23:35:54 +01008025 public void replacePreferredActivity(IntentFilter filter, int match,
8026 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01008027 if (filter.countActions() != 1) {
8028 throw new IllegalArgumentException(
8029 "replacePreferredActivity expects filter to have only 1 action.");
8030 }
8031 if (filter.countCategories() != 1) {
8032 throw new IllegalArgumentException(
8033 "replacePreferredActivity expects filter to have only 1 category.");
8034 }
8035 if (filter.countDataAuthorities() != 0
8036 || filter.countDataPaths() != 0
8037 || filter.countDataSchemes() != 0
8038 || filter.countDataTypes() != 0) {
8039 throw new IllegalArgumentException(
8040 "replacePreferredActivity expects filter to have no data authorities, " +
8041 "paths, schemes or types.");
8042 }
8043 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008044 if (mContext.checkCallingOrSelfPermission(
8045 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8046 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008047 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008048 < Build.VERSION_CODES.FROYO) {
8049 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
8050 + Binder.getCallingUid());
8051 return;
8052 }
8053 mContext.enforceCallingOrSelfPermission(
8054 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8055 }
8056
Dianne Hackborn04505102012-02-29 12:34:04 -08008057 ArrayList<PreferredActivity> removed = null;
Satish Sampath8dbe6122009-06-02 23:35:54 +01008058 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
8059 String action = filter.getAction(0);
8060 String category = filter.getCategory(0);
8061 while (it.hasNext()) {
8062 PreferredActivity pa = it.next();
8063 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008064 if (removed == null) {
8065 removed = new ArrayList<PreferredActivity>();
8066 }
8067 removed.add(pa);
8068 Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
Satish Sampath8dbe6122009-06-02 23:35:54 +01008069 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
8070 }
8071 }
Dianne Hackborn04505102012-02-29 12:34:04 -08008072 if (removed != null) {
8073 for (int i=0; i<removed.size(); i++) {
8074 PreferredActivity pa = removed.get(i);
8075 mSettings.mPreferredActivities.removeFilter(pa);
8076 }
8077 }
Satish Sampath8dbe6122009-06-02 23:35:54 +01008078 addPreferredActivity(filter, match, set, activity);
8079 }
8080 }
8081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008083 final int uid = Binder.getCallingUid();
8084 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008086 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008087 if (pkg == null || pkg.applicationInfo.uid != uid) {
8088 if (mContext.checkCallingOrSelfPermission(
8089 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
8090 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07008091 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008092 < Build.VERSION_CODES.FROYO) {
8093 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
8094 + Binder.getCallingUid());
8095 return;
8096 }
8097 mContext.enforceCallingOrSelfPermission(
8098 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
8099 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08008100 }
8101
Kenny Root447106f2011-03-23 11:00:15 -07008102 if (clearPackagePreferredActivitiesLPw(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008103 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008104 }
8105 }
8106 }
8107
Kenny Root447106f2011-03-23 11:00:15 -07008108 boolean clearPackagePreferredActivitiesLPw(String packageName) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008109 ArrayList<PreferredActivity> removed = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
8111 while (it.hasNext()) {
8112 PreferredActivity pa = it.next();
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008113 if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08008114 if (removed == null) {
8115 removed = new ArrayList<PreferredActivity>();
8116 }
8117 removed.add(pa);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 }
8119 }
Dianne Hackborn04505102012-02-29 12:34:04 -08008120 if (removed != null) {
8121 for (int i=0; i<removed.size(); i++) {
8122 PreferredActivity pa = removed.get(i);
8123 mSettings.mPreferredActivities.removeFilter(pa);
8124 }
8125 return true;
8126 }
8127 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 }
8129
8130 public int getPreferredActivities(List<IntentFilter> outFilters,
8131 List<ComponentName> outActivities, String packageName) {
8132
8133 int num = 0;
Kenny Root447106f2011-03-23 11:00:15 -07008134 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008136 final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07008138 final PreferredActivity pa = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 if (packageName == null
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008140 || pa.mPref.mComponent.getPackageName().equals(packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (outFilters != null) {
8142 outFilters.add(new IntentFilter(pa));
8143 }
8144 if (outActivities != null) {
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08008145 outActivities.add(pa.mPref.mComponent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 }
8147 }
8148 }
8149 }
8150
8151 return num;
8152 }
8153
Amith Yamasani483f3b02012-03-13 16:08:00 -07008154 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008155 public void setApplicationEnabledSetting(String appPackageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008156 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008157 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008158 setEnabledSetting(appPackageName, null, newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 }
8160
Amith Yamasani483f3b02012-03-13 16:08:00 -07008161 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008163 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008164 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 setEnabledSetting(componentName.getPackageName(),
Amith Yamasani483f3b02012-03-13 16:08:00 -07008166 componentName.getClassName(), newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 }
8168
8169 private void setEnabledSetting(
Amith Yamasani483f3b02012-03-13 16:08:00 -07008170 final String packageName, String className, int newState, final int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008171 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
8172 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -07008173 || newState == COMPONENT_ENABLED_STATE_DISABLED
8174 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 throw new IllegalArgumentException("Invalid new component state: "
8176 + newState);
8177 }
8178 PackageSetting pkgSetting;
8179 final int uid = Binder.getCallingUid();
8180 final int permission = mContext.checkCallingPermission(
8181 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasani483f3b02012-03-13 16:08:00 -07008182 checkValidCaller(uid, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008184 boolean sendNow = false;
8185 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008186 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008188 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -07008189
8190 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008192 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008193 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008194 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008196 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008197 }
8198 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008199 "Unknown component: " + packageName
8200 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008202 // Allow root and verify that userId is not being specified by a different user
Amith Yamasani13593602012-03-22 16:16:17 -07008203 if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 throw new SecurityException(
8205 "Permission Denial: attempt to change component state from pid="
8206 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -07008207 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008208 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008209 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008210 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -07008211 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008212 // Nothing to do
8213 return;
8214 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008215 pkgSetting.setEnabled(newState, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07008216 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008217 } else {
8218 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -08008219 // First, verify that this is a valid class name.
8220 PackageParser.Package pkg = pkgSetting.pkg;
8221 if (pkg == null || !pkg.hasComponentClassName(className)) {
8222 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
8223 throw new IllegalArgumentException("Component class " + className
8224 + " does not exist in " + packageName);
8225 } else {
8226 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
8227 + className + " does not exist in " + packageName);
8228 }
8229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 switch (newState) {
8231 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008232 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008233 return;
8234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 break;
8236 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008237 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008238 return;
8239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 break;
8241 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -07008242 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008243 return;
8244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 break;
8246 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008247 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008248 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008249 }
8250 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07008251 mSettings.writePackageRestrictionsLPr(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07008252 packageUid = UserId.getUid(userId, pkgSetting.appId);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008253 components = mPendingBroadcasts.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07008254 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008255 if (newPackage) {
8256 components = new ArrayList<String>();
8257 }
8258 if (!components.contains(componentName)) {
8259 components.add(componentName);
8260 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008261 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
8262 sendNow = true;
8263 // Purge entry from pending broadcast list if another one exists already
8264 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008265 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008266 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008267 if (newPackage) {
8268 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008269 }
8270 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
8271 // Schedule a message
8272 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
8273 }
8274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008275 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 long callingId = Binder.clearCallingIdentity();
8278 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008279 if (sendNow) {
8280 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008281 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008283 } finally {
8284 Binder.restoreCallingIdentity(callingId);
8285 }
8286 }
8287
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008288 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008289 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08008290 if (DEBUG_INSTALL)
8291 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
8292 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08008293 Bundle extras = new Bundle(4);
8294 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
8295 String nameList[] = new String[componentNames.size()];
8296 componentNames.toArray(nameList);
8297 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008298 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
8299 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -07008300 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
8301 UserId.getUserId(packageUid));
Dianne Hackborne7f97212011-02-24 14:40:20 -08008302 }
8303
Amith Yamasani483f3b02012-03-13 16:08:00 -07008304 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008305 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008306 final int uid = Binder.getCallingUid();
8307 final int permission = mContext.checkCallingOrSelfPermission(
8308 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
8309 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasani483f3b02012-03-13 16:08:00 -07008310 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008311 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -08008312 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008313 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008314 uid, userId)) {
8315 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08008316 }
8317 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008318 }
8319
Jacek Surazski65e13172009-04-28 15:26:38 +02008320 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008321 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +02008322 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008323 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02008324 }
8325 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008326
Amith Yamasani483f3b02012-03-13 16:08:00 -07008327 @Override
8328 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008329 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008330 int uid = Binder.getCallingUid();
8331 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008332 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008334 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 }
8336 }
8337
Amith Yamasani483f3b02012-03-13 16:08:00 -07008338 @Override
8339 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008340 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008341 int uid = Binder.getCallingUid();
8342 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008343 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008344 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008345 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 }
8347 }
8348
8349 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -07008350 enforceSystemOrRoot("Only the system can request entering safe mode");
8351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008352 if (!mSystemReady) {
8353 mSafeMode = true;
8354 }
8355 }
8356
8357 public void systemReady() {
8358 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008359
8360 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008361 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008362 mContext.getContentResolver(),
8363 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008364 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008365 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008366 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 }
8369
8370 public boolean isSafeMode() {
8371 return mSafeMode;
8372 }
8373
8374 public boolean hasSystemUidErrors() {
8375 return mHasSystemUidErrors;
8376 }
8377
8378 static String arrayToString(int[] array) {
8379 StringBuffer buf = new StringBuffer(128);
8380 buf.append('[');
8381 if (array != null) {
8382 for (int i=0; i<array.length; i++) {
8383 if (i > 0) buf.append(", ");
8384 buf.append(array[i]);
8385 }
8386 }
8387 buf.append(']');
8388 return buf.toString();
8389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008390
Kenny Root447106f2011-03-23 11:00:15 -07008391 static class DumpState {
8392 public static final int DUMP_LIBS = 1 << 0;
8393
8394 public static final int DUMP_FEATURES = 1 << 1;
8395
8396 public static final int DUMP_RESOLVERS = 1 << 2;
8397
8398 public static final int DUMP_PERMISSIONS = 1 << 3;
8399
8400 public static final int DUMP_PACKAGES = 1 << 4;
8401
8402 public static final int DUMP_SHARED_USERS = 1 << 5;
8403
8404 public static final int DUMP_MESSAGES = 1 << 6;
8405
8406 public static final int DUMP_PROVIDERS = 1 << 7;
8407
Kenny Root05ca4c92011-09-15 10:36:25 -07008408 public static final int DUMP_VERIFIERS = 1 << 8;
8409
Kenny Root447106f2011-03-23 11:00:15 -07008410 public static final int OPTION_SHOW_FILTERS = 1 << 0;
8411
8412 private int mTypes;
8413
8414 private int mOptions;
8415
8416 private boolean mTitlePrinted;
8417
8418 private SharedUserSetting mSharedUser;
8419
8420 public boolean isDumping(int type) {
8421 if (mTypes == 0) {
8422 return true;
8423 }
8424
8425 return (mTypes & type) != 0;
8426 }
8427
8428 public void setDump(int type) {
8429 mTypes |= type;
8430 }
8431
8432 public boolean isOptionEnabled(int option) {
8433 return (mOptions & option) != 0;
8434 }
8435
8436 public void setOptionEnabled(int option) {
8437 mOptions |= option;
8438 }
8439
8440 public boolean onTitlePrinted() {
8441 final boolean printed = mTitlePrinted;
8442 mTitlePrinted = true;
8443 return printed;
8444 }
8445
8446 public boolean getTitlePrinted() {
8447 return mTitlePrinted;
8448 }
8449
8450 public void setTitlePrinted(boolean enabled) {
8451 mTitlePrinted = enabled;
8452 }
8453
8454 public SharedUserSetting getSharedUser() {
8455 return mSharedUser;
8456 }
8457
8458 public void setSharedUser(SharedUserSetting user) {
8459 mSharedUser = user;
8460 }
8461 }
8462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 @Override
8464 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8465 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
8466 != PackageManager.PERMISSION_GRANTED) {
8467 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8468 + Binder.getCallingPid()
8469 + ", uid=" + Binder.getCallingUid()
8470 + " without permission "
8471 + android.Manifest.permission.DUMP);
8472 return;
8473 }
8474
Kenny Root447106f2011-03-23 11:00:15 -07008475 DumpState dumpState = new DumpState();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008476
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008477 String packageName = null;
8478
8479 int opti = 0;
8480 while (opti < args.length) {
8481 String opt = args[opti];
8482 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8483 break;
8484 }
8485 opti++;
8486 if ("-a".equals(opt)) {
8487 // Right now we only know how to print all.
8488 } else if ("-h".equals(opt)) {
8489 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008490 pw.println(" [-h] [-f] [cmd] ...");
8491 pw.println(" -f: print details of intent filters");
8492 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008493 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008494 pw.println(" l[ibraries]: list known shared libraries");
8495 pw.println(" f[ibraries]: list device features");
8496 pw.println(" r[esolvers]: dump intent resolvers");
8497 pw.println(" perm[issions]: dump permissions");
8498 pw.println(" prov[iders]: dump content providers");
8499 pw.println(" p[ackages]: dump installed packages");
8500 pw.println(" s[hared-users]: dump shared user IDs");
8501 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -07008502 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008503 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008504 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008505 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -07008506 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008507 } else {
8508 pw.println("Unknown argument: " + opt + "; use -h for help");
8509 }
8510 }
8511
8512 // Is the caller requesting to dump a particular piece of data?
8513 if (opti < args.length) {
8514 String cmd = args[opti];
8515 opti++;
8516 // Is this a package name?
8517 if ("android".equals(cmd) || cmd.contains(".")) {
8518 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008519 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008520 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008521 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008522 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008523 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008524 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008525 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008526 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008527 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008528 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008529 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008530 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008531 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008532 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008533 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008534 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -07008535 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
8536 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008537 }
8538 }
Kenny Root447106f2011-03-23 11:00:15 -07008539
8540 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008541 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -07008542 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
8543 if (dumpState.onTitlePrinted())
8544 pw.println(" ");
8545 pw.println("Verifiers:");
8546 pw.print(" Required: ");
8547 pw.print(mRequiredVerifierPackage);
8548 pw.print(" (uid=");
Amith Yamasani483f3b02012-03-13 16:08:00 -07008549 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
Kenny Root05ca4c92011-09-15 10:36:25 -07008550 pw.println(")");
8551 }
8552
Kenny Root447106f2011-03-23 11:00:15 -07008553 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
8554 if (dumpState.onTitlePrinted())
8555 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008556 pw.println("Libraries:");
Kenny Root447106f2011-03-23 11:00:15 -07008557 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008558 while (it.hasNext()) {
8559 String name = it.next();
8560 pw.print(" ");
8561 pw.print(name);
8562 pw.print(" -> ");
8563 pw.println(mSharedLibraries.get(name));
8564 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008565 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008566
Kenny Root447106f2011-03-23 11:00:15 -07008567 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
8568 if (dumpState.onTitlePrinted())
8569 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008570 pw.println("Features:");
8571 Iterator<String> it = mAvailableFeatures.keySet().iterator();
8572 while (it.hasNext()) {
8573 String name = it.next();
8574 pw.print(" ");
8575 pw.println(name);
8576 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008577 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008578
Kenny Root447106f2011-03-23 11:00:15 -07008579 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
8580 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
8581 : "Activity Resolver Table:", " ", packageName,
8582 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8583 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008584 }
Kenny Root447106f2011-03-23 11:00:15 -07008585 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
8586 : "Receiver Resolver Table:", " ", packageName,
8587 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8588 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008589 }
Kenny Root447106f2011-03-23 11:00:15 -07008590 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
8591 : "Service Resolver Table:", " ", packageName,
8592 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8593 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008594 }
Kenny Root447106f2011-03-23 11:00:15 -07008595 if (mSettings.mPreferredActivities.dump(pw,
8596 dumpState.getTitlePrinted() ? "\nPreferred Activities:"
8597 : "Preferred Activities:", " ",
8598 packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8599 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008600 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008601 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008602
Kenny Root447106f2011-03-23 11:00:15 -07008603 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
8604 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008606
Kenny Root447106f2011-03-23 11:00:15 -07008607 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
8608 boolean printedSomething = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008609 for (PackageParser.Provider p : mProvidersByComponent.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008610 if (packageName != null && !packageName.equals(p.info.packageName)) {
8611 continue;
8612 }
8613 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -07008614 if (dumpState.onTitlePrinted())
8615 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008616 pw.println("Registered ContentProviders:");
8617 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008618 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008619 pw.print(" "); pw.print(p.getComponentShortName()); pw.println(":");
8620 pw.print(" "); pw.println(p.toString());
8621 }
8622 printedSomething = false;
8623 for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
8624 PackageParser.Provider p = entry.getValue();
8625 if (packageName != null && !packageName.equals(p.info.packageName)) {
8626 continue;
8627 }
8628 if (!printedSomething) {
8629 if (dumpState.onTitlePrinted())
8630 pw.println(" ");
8631 pw.println("ContentProvider Authorities:");
8632 printedSomething = true;
8633 }
8634 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
8635 pw.print(" "); pw.println(p.toString());
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008636 }
8637 }
8638
Kenny Root447106f2011-03-23 11:00:15 -07008639 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
8640 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 }
Kenny Root447106f2011-03-23 11:00:15 -07008642
8643 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
8644 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008645 }
Kenny Root447106f2011-03-23 11:00:15 -07008646
8647 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
8648 if (dumpState.onTitlePrinted())
8649 pw.println(" ");
8650 mSettings.dumpReadMessagesLPr(pw, dumpState);
8651
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008652 pw.println(" ");
8653 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -07008654 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008655 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008656 try {
8657 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -07008658 final int avail = in.available();
8659 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008660 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008661 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008662 } catch (FileNotFoundException e) {
8663 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008664 } finally {
8665 if (in != null) {
8666 try {
8667 in.close();
Kenny Root447106f2011-03-23 11:00:15 -07008668 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008669 }
8670 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008671 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008673 }
8674 }
8675
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008676 // ------- apps on sdcard specific code -------
8677 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -07008678
Kenny Root305bcbf2010-09-03 07:56:38 -07008679 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -07008680
Kenny Root305bcbf2010-09-03 07:56:38 -07008681 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -07008682
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008683 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008684
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008685 private String getEncryptKey() {
8686 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07008687 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
8688 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008689 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07008690 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
8691 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008692 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008693 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008694 return null;
8695 }
8696 }
8697 return sdEncKey;
8698 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008699 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008700 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07008701 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -07008702 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -07008703 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008704 }
Rich Cannings8d578832010-09-09 15:12:40 -07008705
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008706 }
8707
Kenny Root447106f2011-03-23 11:00:15 -07008708 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -07008709 int tmpIdx = 1;
8710 String list[] = PackageHelper.getSecureContainerList();
8711 if (list != null) {
8712 for (final String name : list) {
8713 // Ignore null and non-temporary container entries
8714 if (name == null || !name.startsWith(mTempContainerPrefix)) {
8715 continue;
8716 }
8717
8718 String subStr = name.substring(mTempContainerPrefix.length());
8719 try {
8720 int cid = Integer.parseInt(subStr);
8721 if (cid >= tmpIdx) {
8722 tmpIdx = cid + 1;
8723 }
8724 } catch (NumberFormatException e) {
8725 }
8726 }
8727 }
8728 return mTempContainerPrefix + tmpIdx;
8729 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008730
Kenny Root447106f2011-03-23 11:00:15 -07008731 /*
8732 * Update media status on PackageManager.
8733 */
8734 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
8735 int callingUid = Binder.getCallingUid();
8736 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
8737 throw new SecurityException("Media status can only be updated by the system");
8738 }
8739 // reader; this apparently protects mMediaMounted, but should probably
8740 // be a different lock in that case.
8741 synchronized (mPackages) {
8742 Log.i(TAG, "Updating external media status from "
8743 + (mMediaMounted ? "mounted" : "unmounted") + " to "
8744 + (mediaStatus ? "mounted" : "unmounted"));
8745 if (DEBUG_SD_INSTALL)
8746 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
8747 + ", mMediaMounted=" + mMediaMounted);
8748 if (mediaStatus == mMediaMounted) {
8749 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
8750 : 0, -1);
8751 mHandler.sendMessage(msg);
8752 return;
8753 }
8754 mMediaMounted = mediaStatus;
8755 }
8756 // Queue up an async operation since the package installation may take a
8757 // little while.
8758 mHandler.post(new Runnable() {
8759 public void run() {
Kenny Root447106f2011-03-23 11:00:15 -07008760 updateExternalMediaStatusInner(mediaStatus, reportStatus);
8761 }
8762 });
8763 }
8764
Kenny Root51a573c2012-05-17 13:30:28 -07008765 /**
8766 * Called by MountService when the initial ASECs to scan are available.
8767 * Should block until all the ASEC containers are finished being scanned.
8768 */
8769 public void scanAvailableAsecs() {
8770 updateExternalMediaStatusInner(true, false);
8771 }
8772
Kenny Root447106f2011-03-23 11:00:15 -07008773 /*
8774 * Collect information of applications on external media, map them against
8775 * existing containers and update information based on current mount status.
8776 * Please note that we always have to report status if reportStatus has been
8777 * set to true especially when unloading packages.
8778 */
Kenny Root6dceb882012-04-12 14:23:49 -07008779 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus) {
Kenny Root447106f2011-03-23 11:00:15 -07008780 // Collection of uids
8781 int uidArr[] = null;
8782 // Collection of stale containers
8783 HashSet<String> removeCids = new HashSet<String>();
8784 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07008785 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -07008786 // Get list of secure containers.
8787 final String list[] = PackageHelper.getSecureContainerList();
8788 if (list == null || list.length == 0) {
8789 Log.i(TAG, "No secure containers on sdcard");
8790 } else {
8791 // Process list of secure containers and categorize them
8792 // as active or stale based on their package internal state.
8793 int uidList[] = new int[list.length];
8794 int num = 0;
8795 // reader
8796 synchronized (mPackages) {
8797 for (String cid : list) {
Kenny Root447106f2011-03-23 11:00:15 -07008798 if (DEBUG_SD_INSTALL)
8799 Log.i(TAG, "Processing container " + cid);
Kenny Rootc7a89992012-06-05 15:13:17 -07008800 String pkgName = getAsecPackageName(cid);
Kenny Root447106f2011-03-23 11:00:15 -07008801 if (pkgName == null) {
8802 if (DEBUG_SD_INSTALL)
8803 Log.i(TAG, "Container : " + cid + " stale");
8804 removeCids.add(cid);
8805 continue;
8806 }
8807 if (DEBUG_SD_INSTALL)
8808 Log.i(TAG, "Looking for pkg : " + pkgName);
Kenny Rootc7a89992012-06-05 15:13:17 -07008809
8810 final PackageSetting ps = mSettings.mPackages.get(pkgName);
8811 if (ps == null) {
8812 Log.i(TAG, "Deleting container with no matching settings " + cid);
8813 removeCids.add(cid);
8814 continue;
8815 }
8816
8817 final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
Kenny Root447106f2011-03-23 11:00:15 -07008818 // The package status is changed only if the code path
8819 // matches between settings and the container id.
Kenny Rootc7a89992012-06-05 15:13:17 -07008820 if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
8821 if (DEBUG_SD_INSTALL) {
Kenny Root447106f2011-03-23 11:00:15 -07008822 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
8823 + " at code path: " + ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07008824 }
8825
Kenny Root447106f2011-03-23 11:00:15 -07008826 // We do have a valid package installed on sdcard
8827 processCids.put(args, ps.codePathString);
Kenny Rootc7a89992012-06-05 15:13:17 -07008828 final int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -07008829 if (uid != -1) {
8830 uidList[num++] = uid;
8831 }
8832 } else {
Kenny Rootc7a89992012-06-05 15:13:17 -07008833 Log.i(TAG, "Deleting stale container for " + cid);
Kenny Root447106f2011-03-23 11:00:15 -07008834 removeCids.add(cid);
8835 }
8836 }
8837 }
8838
8839 if (num > 0) {
8840 // Sort uid list
8841 Arrays.sort(uidList, 0, num);
8842 // Throw away duplicates
8843 uidArr = new int[num];
8844 uidArr[0] = uidList[0];
8845 int di = 0;
8846 for (int i = 1; i < num; i++) {
8847 if (uidList[i - 1] != uidList[i]) {
8848 uidArr[di++] = uidList[i];
8849 }
8850 }
8851 }
8852 }
8853 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -07008854 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -07008855 if (DEBUG_SD_INSTALL)
8856 Log.i(TAG, "Loading packages");
8857 loadMediaPackages(processCids, uidArr, removeCids);
8858 startCleaningPackages();
8859 } else {
8860 if (DEBUG_SD_INSTALL)
8861 Log.i(TAG, "Unloading packages");
8862 unloadMediaPackages(processCids, uidArr, reportStatus);
8863 }
8864 }
8865
8866 private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
8867 int uidArr[], IIntentReceiver finishedReceiver) {
8868 int size = pkgList.size();
8869 if (size > 0) {
8870 // Send broadcasts here
8871 Bundle extras = new Bundle();
8872 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
8873 .toArray(new String[size]));
8874 if (uidArr != null) {
8875 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
8876 }
8877 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
8878 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Amith Yamasani13593602012-03-22 16:16:17 -07008879 sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserId.USER_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07008880 }
8881 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008882
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07008883 /*
Kenny Root447106f2011-03-23 11:00:15 -07008884 * Look at potentially valid container ids from processCids If package
8885 * information doesn't match the one on record or package scanning fails,
8886 * the cid is added to list of removeCids. We currently don't delete stale
8887 * containers.
8888 */
Kenny Root6dceb882012-04-12 14:23:49 -07008889 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07008890 HashSet<String> removeCids) {
8891 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07008892 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -07008893 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -07008894 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07008895 String codePath = processCids.get(args);
8896 if (DEBUG_SD_INSTALL)
8897 Log.i(TAG, "Loading container : " + args.cid);
8898 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8899 try {
8900 // Make sure there are no container errors first.
8901 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
8902 Slog.e(TAG, "Failed to mount cid : " + args.cid
8903 + " when installing from sdcard");
8904 continue;
8905 }
8906 // Check code path here.
8907 if (codePath == null || !codePath.equals(args.getCodePath())) {
8908 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
8909 + " does not match one in settings " + codePath);
8910 continue;
8911 }
8912 // Parse package
Kenny Root51a573c2012-05-17 13:30:28 -07008913 int parseFlags = mDefParseFlags;
8914 if (args.isExternal()) {
8915 parseFlags |= PackageParser.PARSE_ON_SDCARD;
8916 }
Kenny Rootc7a89992012-06-05 15:13:17 -07008917 if (args.isFwdLocked()) {
8918 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
8919 }
Kenny Root51a573c2012-05-17 13:30:28 -07008920
Kenny Root447106f2011-03-23 11:00:15 -07008921 doGc = true;
8922 synchronized (mInstallLock) {
8923 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
8924 0, 0);
8925 // Scan the package
8926 if (pkg != null) {
8927 /*
8928 * TODO why is the lock being held? doPostInstall is
8929 * called in other places without the lock. This needs
8930 * to be straightened out.
8931 */
8932 // writer
8933 synchronized (mPackages) {
8934 retCode = PackageManager.INSTALL_SUCCEEDED;
8935 pkgList.add(pkg.packageName);
8936 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -07008937 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
8938 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07008939 }
8940 } else {
8941 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
8942 }
8943 }
8944
8945 } finally {
8946 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
8947 // Don't destroy container here. Wait till gc clears things
8948 // up.
8949 removeCids.add(args.cid);
8950 }
8951 }
8952 }
8953 // writer
8954 synchronized (mPackages) {
8955 // If the platform SDK has changed since the last time we booted,
8956 // we need to re-grant app permission to catch any new ones that
8957 // appear. This is really a hack, and means that apps can in some
8958 // cases get permissions that the user didn't initially explicitly
8959 // allow... it would be nice to have some better way to handle
8960 // this situation.
8961 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
8962 if (regrantPermissions)
8963 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
8964 + mSdkVersion + "; regranting permissions for external storage");
8965 mSettings.mExternalSdkPlatform = mSdkVersion;
8966
8967 // Make sure group IDs have been assigned, and any permission
8968 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -08008969 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
8970 | (regrantPermissions
8971 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
8972 : 0));
Kenny Root447106f2011-03-23 11:00:15 -07008973 // can downgrade to reader
8974 // Persist settings
8975 mSettings.writeLPr();
8976 }
8977 // Send a broadcast to let everyone know we are done processing
8978 if (pkgList.size() > 0) {
8979 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
8980 }
8981 // Force gc to avoid any stale parser references that we might have.
8982 if (doGc) {
8983 Runtime.getRuntime().gc();
8984 }
8985 // List stale containers and destroy stale temporary containers.
8986 if (removeCids != null) {
8987 for (String cid : removeCids) {
8988 if (cid.startsWith(mTempContainerPrefix)) {
8989 Log.i(TAG, "Destroying stale temporary container " + cid);
8990 PackageHelper.destroySdDir(cid);
8991 } else {
8992 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008993 }
8994 }
Kenny Root447106f2011-03-23 11:00:15 -07008995 }
8996 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008997
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008998 /*
Kenny Root447106f2011-03-23 11:00:15 -07008999 * Utility method to unload a list of specified containers
9000 */
Kenny Root6dceb882012-04-12 14:23:49 -07009001 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009002 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07009003 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07009004 synchronized (mInstallLock) {
9005 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009006 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009007 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009008 }
9009
Kenny Root447106f2011-03-23 11:00:15 -07009010 /*
9011 * Unload packages mounted on external media. This involves deleting package
9012 * data from internal structures, sending broadcasts about diabled packages,
9013 * gc'ing to free up references, unmounting all secure containers
9014 * corresponding to packages on external media, and posting a
9015 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
9016 * that we always have to post this message if status has been requested no
9017 * matter what.
9018 */
Kenny Root6dceb882012-04-12 14:23:49 -07009019 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07009020 final boolean reportStatus) {
9021 if (DEBUG_SD_INSTALL)
9022 Log.i(TAG, "unloading media packages");
9023 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07009024 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
9025 final Set<AsecInstallArgs> keys = processCids.keySet();
9026 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07009027 String pkgName = args.getPackageName();
9028 if (DEBUG_SD_INSTALL)
9029 Log.i(TAG, "Trying to unload pkg : " + pkgName);
9030 // Delete package internally
9031 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9032 synchronized (mInstallLock) {
9033 boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
9034 outInfo, false);
9035 if (res) {
9036 pkgList.add(pkgName);
9037 } else {
9038 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
9039 failedList.add(args);
9040 }
9041 }
9042 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009043
Kenny Root447106f2011-03-23 11:00:15 -07009044 // reader
9045 synchronized (mPackages) {
9046 // We didn't update the settings after removing each package;
9047 // write them now for all packages.
9048 mSettings.writeLPr();
9049 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009050
Kenny Root447106f2011-03-23 11:00:15 -07009051 // We have to absolutely send UPDATED_MEDIA_STATUS only
9052 // after confirming that all the receivers processed the ordered
9053 // broadcast when packages get disabled, force a gc to clean things up.
9054 // and unload all the containers.
9055 if (pkgList.size() > 0) {
9056 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
9057 public void performReceive(Intent intent, int resultCode, String data,
9058 Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
9059 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
9060 reportStatus ? 1 : 0, 1, keys);
9061 mHandler.sendMessage(msg);
9062 }
9063 });
9064 } else {
9065 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
9066 keys);
9067 mHandler.sendMessage(msg);
9068 }
9069 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07009070
Kenny Root447106f2011-03-23 11:00:15 -07009071 public void movePackage(final String packageName, final IPackageMoveObserver observer,
9072 final int flags) {
9073 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
9074 int returnCode = PackageManager.MOVE_SUCCEEDED;
9075 int currFlags = 0;
9076 int newFlags = 0;
9077 // reader
9078 synchronized (mPackages) {
9079 PackageParser.Package pkg = mPackages.get(packageName);
9080 if (pkg == null) {
9081 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9082 } else {
9083 // Disable moving fwd locked apps and system packages
9084 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
9085 Slog.w(TAG, "Cannot move system application");
9086 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -07009087 } else if (pkg.mOperationPending) {
9088 Slog.w(TAG, "Attempt to move package which has pending operations");
9089 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
9090 } else {
9091 // Find install location first
9092 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
9093 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
9094 Slog.w(TAG, "Ambigous flags specified for move location.");
9095 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9096 } else {
9097 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
9098 : PackageManager.INSTALL_INTERNAL;
9099 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
9100 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -07009101
Kenny Root447106f2011-03-23 11:00:15 -07009102 if (newFlags == currFlags) {
9103 Slog.w(TAG, "No move required. Trying to move to same location");
9104 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -07009105 } else {
9106 if (isForwardLocked(pkg)) {
9107 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9108 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
9109 }
Kenny Root447106f2011-03-23 11:00:15 -07009110 }
9111 }
9112 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9113 pkg.mOperationPending = true;
9114 }
9115 }
9116 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009117
Kenny Root447106f2011-03-23 11:00:15 -07009118 /*
9119 * TODO this next block probably shouldn't be inside the lock. We
9120 * can't guarantee these won't change after this is fired off
9121 * anyway.
9122 */
9123 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root6dceb882012-04-12 14:23:49 -07009124 processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1),
9125 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -07009126 } else {
9127 Message msg = mHandler.obtainMessage(INIT_COPY);
9128 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -07009129 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -07009130 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Kenny Root6dceb882012-04-12 14:23:49 -07009131 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07009132 msg.obj = mp;
9133 mHandler.sendMessage(msg);
9134 }
9135 }
9136 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009137
Kenny Root447106f2011-03-23 11:00:15 -07009138 private void processPendingMove(final MoveParams mp, final int currentStatus) {
9139 // Queue up an async operation since the package deletion may take a
9140 // little while.
9141 mHandler.post(new Runnable() {
9142 public void run() {
9143 // TODO fix this; this does nothing.
9144 mHandler.removeCallbacks(this);
9145 int returnCode = currentStatus;
9146 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
9147 int uidArr[] = null;
9148 ArrayList<String> pkgList = null;
9149 synchronized (mPackages) {
9150 PackageParser.Package pkg = mPackages.get(mp.packageName);
9151 if (pkg == null) {
9152 Slog.w(TAG, " Package " + mp.packageName
9153 + " doesn't exist. Aborting move");
9154 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9155 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
9156 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
9157 + mp.srcArgs.getCodePath() + " to "
9158 + pkg.applicationInfo.sourceDir
9159 + " Aborting move and returning error");
9160 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
9161 } else {
9162 uidArr = new int[] {
9163 pkg.applicationInfo.uid
9164 };
9165 pkgList = new ArrayList<String>();
9166 pkgList.add(mp.packageName);
9167 }
9168 }
9169 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9170 // Send resources unavailable broadcast
9171 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
9172 // Update package code and resource paths
9173 synchronized (mInstallLock) {
9174 synchronized (mPackages) {
9175 PackageParser.Package pkg = mPackages.get(mp.packageName);
9176 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -07009177 if (pkg == null) {
9178 Slog.w(TAG, " Package " + mp.packageName
9179 + " doesn't exist. Aborting move");
9180 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -07009181 } else if (!mp.srcArgs.getCodePath().equals(
9182 pkg.applicationInfo.sourceDir)) {
9183 Slog.w(TAG, "Package " + mp.packageName
9184 + " code path changed from " + mp.srcArgs.getCodePath()
9185 + " to " + pkg.applicationInfo.sourceDir
9186 + " Aborting move and returning error");
9187 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
9188 } else {
9189 final String oldCodePath = pkg.mPath;
9190 final String newCodePath = mp.targetArgs.getCodePath();
9191 final String newResPath = mp.targetArgs.getResourcePath();
9192 final String newNativePath = mp.targetArgs
9193 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -07009194
Kenny Rootbf023582012-05-02 16:56:15 -07009195 try {
9196 final File newNativeDir = new File(newNativePath);
9197
9198 final String libParentDir = newNativeDir.getParentFile()
9199 .getCanonicalPath();
9200 if (newNativeDir.getParentFile().getCanonicalPath()
9201 .equals(pkg.applicationInfo.dataDir)) {
9202 if (mInstaller
9203 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
9204 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9205 } else {
9206 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
9207 new File(newCodePath), newNativeDir);
9208 }
Kenny Root6a6b0072010-10-07 16:46:10 -07009209 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07009210 if (mInstaller.linkNativeLibraryDirectory(
9211 pkg.applicationInfo.dataDir, newNativePath) < 0) {
9212 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9213 }
Kenny Root6a6b0072010-10-07 16:46:10 -07009214 }
Kenny Rootbf023582012-05-02 16:56:15 -07009215 } catch (IOException e) {
9216 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Root6a6b0072010-10-07 16:46:10 -07009217 }
9218
Kenny Rootbf023582012-05-02 16:56:15 -07009219
Kenny Root6a6b0072010-10-07 16:46:10 -07009220 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
9221 pkg.mPath = newCodePath;
9222 // Move dex files around
9223 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
9224 // Moving of dex files failed. Set
9225 // error code and abort move.
9226 pkg.mPath = pkg.mScanPath;
9227 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9228 }
9229 }
9230
9231 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -07009232 pkg.mScanPath = newCodePath;
9233 pkg.applicationInfo.sourceDir = newCodePath;
9234 pkg.applicationInfo.publicSourceDir = newResPath;
9235 pkg.applicationInfo.nativeLibraryDir = newNativePath;
9236 PackageSetting ps = (PackageSetting) pkg.mExtras;
9237 ps.codePath = new File(pkg.applicationInfo.sourceDir);
9238 ps.codePathString = ps.codePath.getPath();
9239 ps.resourcePath = new File(
9240 pkg.applicationInfo.publicSourceDir);
9241 ps.resourcePathString = ps.resourcePath.getPath();
9242 ps.nativeLibraryPathString = newNativePath;
9243 // Set the application info flag
9244 // correctly.
9245 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
9246 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9247 } else {
9248 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9249 }
9250 ps.setFlags(pkg.applicationInfo.flags);
9251 mAppDirs.remove(oldCodePath);
9252 mAppDirs.put(newCodePath, pkg);
9253 // Persist settings
9254 mSettings.writeLPr();
9255 }
9256 }
9257 }
9258 }
9259 // Send resources available broadcast
9260 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
9261 }
9262 }
9263 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
9264 // Clean up failed installation
9265 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -07009266 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
9267 -1);
Kenny Root447106f2011-03-23 11:00:15 -07009268 }
9269 } else {
9270 // Force a gc to clear things up.
9271 Runtime.getRuntime().gc();
9272 // Delete older code
9273 synchronized (mInstallLock) {
9274 mp.srcArgs.doPostDeleteLI(true);
9275 }
9276 }
Kenny Rootdeb11262010-08-02 11:36:21 -07009277
Kenny Root447106f2011-03-23 11:00:15 -07009278 // Allow more operations on this file if we didn't fail because
9279 // an operation was already pending for this package.
9280 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
9281 synchronized (mPackages) {
9282 PackageParser.Package pkg = mPackages.get(mp.packageName);
9283 if (pkg != null) {
9284 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -07009285 }
9286 }
Kenny Root447106f2011-03-23 11:00:15 -07009287 }
Kenny Rootdeb11262010-08-02 11:36:21 -07009288
Kenny Root447106f2011-03-23 11:00:15 -07009289 IPackageMoveObserver observer = mp.observer;
9290 if (observer != null) {
9291 try {
9292 observer.packageMoved(mp.packageName, returnCode);
9293 } catch (RemoteException e) {
9294 Log.i(TAG, "Observer no longer exists.");
9295 }
9296 }
9297 }
9298 });
9299 }
9300
9301 public boolean setInstallLocation(int loc) {
9302 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
9303 null);
9304 if (getInstallLocation() == loc) {
9305 return true;
9306 }
9307 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
9308 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
9309 android.provider.Settings.System.putInt(mContext.getContentResolver(),
9310 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
9311 return true;
9312 }
9313 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009314 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -07009315
Kenny Root447106f2011-03-23 11:00:15 -07009316 public int getInstallLocation() {
9317 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
9318 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION,
9319 PackageHelper.APP_INSTALL_AUTO);
9320 }
Amith Yamasani0b285492011-04-14 17:35:23 -07009321
9322 public UserInfo createUser(String name, int flags) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009323 // TODO(kroot): Add a real permission for creating users
9324 enforceSystemOrRoot("Only the system can create users");
9325
Amith Yamasani13593602012-03-22 16:16:17 -07009326 UserInfo userInfo = sUserManager.createUser(name, flags);
9327 if (userInfo != null) {
9328 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
9329 addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
9330 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9331 }
Amith Yamasani0b285492011-04-14 17:35:23 -07009332 return userInfo;
9333 }
9334
9335 public boolean removeUser(int userId) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009336 // TODO(kroot): Add a real permission for removing users
9337 enforceSystemOrRoot("Only the system can remove users");
9338
Amith Yamasani13593602012-03-22 16:16:17 -07009339 if (userId == 0 || !sUserManager.exists(userId)) {
Amith Yamasani0b285492011-04-14 17:35:23 -07009340 return false;
9341 }
Amith Yamasani13593602012-03-22 16:16:17 -07009342
9343 cleanUpUser(userId);
9344
9345 if (sUserManager.removeUser(userId)) {
9346 // Let other services shutdown any activity
9347 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
9348 addedIntent.putExtra(Intent.EXTRA_USERID, userId);
9349 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9350 }
9351 sUserManager.removePackageFolders(userId);
Amith Yamasani0b285492011-04-14 17:35:23 -07009352 return true;
9353 }
Kenny Root0aaa0d92011-09-12 16:42:55 -07009354
Amith Yamasani13593602012-03-22 16:16:17 -07009355 private void cleanUpUser(int userId) {
9356 // Disable all the packages for the user first
9357 synchronized (mPackages) {
9358 Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
9359 for (Entry<String, PackageSetting> entry : entries) {
9360 entry.getValue().removeUser(userId);
9361 }
9362 if (mDirtyUsers.remove(userId));
9363 mSettings.removeUserLPr(userId);
9364 }
9365 }
9366
Kenny Root0aaa0d92011-09-12 16:42:55 -07009367 @Override
9368 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
9369 mContext.enforceCallingOrSelfPermission(
9370 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
9371 "Only package verification agents can read the verifier device identity");
9372
9373 synchronized (mPackages) {
9374 return mSettings.getVerifierDeviceIdentityLPw();
9375 }
9376 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009377
Amith Yamasani13593602012-03-22 16:16:17 -07009378 @Override
Amith Yamasani742a6712011-05-04 14:49:28 -07009379 public List<UserInfo> getUsers() {
Amith Yamasani13593602012-03-22 16:16:17 -07009380 enforceSystemOrRoot("Only the system can query users");
9381 return sUserManager.getUsers();
9382 }
9383
9384 @Override
9385 public UserInfo getUser(int userId) {
Amith Yamasani5bb87cd2012-06-14 11:32:13 -07009386 enforceSystemOrRoot("Only the system can query user");
Amith Yamasani13593602012-03-22 16:16:17 -07009387 return sUserManager.getUser(userId);
9388 }
9389
9390 @Override
Amith Yamasanib8151ec2012-04-18 18:02:48 -07009391 public void setUserName(int userId, String name) {
Amith Yamasani13593602012-03-22 16:16:17 -07009392 enforceSystemOrRoot("Only the system can rename users");
Amith Yamasanib8151ec2012-04-18 18:02:48 -07009393 sUserManager.setUserName(userId, name);
9394 }
9395
9396 @Override
9397 public ParcelFileDescriptor setUserIcon(int userId) {
9398 enforceSystemOrRoot("Only the system can update users");
9399 return sUserManager.setUserIcon(userId);
Amith Yamasani742a6712011-05-04 14:49:28 -07009400 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009401
9402 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009403 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009404 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
9405 if (READ_EXTERNAL_STORAGE.equals(permission)) {
9406 synchronized (mPackages) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -07009407 if (mSettings.mReadExternalStorageEnforced == null
9408 || mSettings.mReadExternalStorageEnforced != enforced) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009409 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009410 mSettings.writeLPr();
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07009411
9412 // kill any non-foreground processes so we restart them and
9413 // grant/revoke the GID.
9414 final IActivityManager am = ActivityManagerNative.getDefault();
9415 if (am != null) {
9416 final long token = Binder.clearCallingIdentity();
9417 try {
9418 am.killProcessesBelowForeground("setPermissionEnforcement");
9419 } catch (RemoteException e) {
9420 } finally {
9421 Binder.restoreCallingIdentity(token);
9422 }
9423 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009424 }
9425 }
9426 } else {
9427 throw new IllegalArgumentException("No selective enforcement for " + permission);
9428 }
9429 }
9430
9431 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009432 public boolean isPermissionEnforced(String permission) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009433 synchronized (mPackages) {
9434 return isPermissionEnforcedLocked(permission);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009435 }
9436 }
9437
9438 private boolean isPermissionEnforcedLocked(String permission) {
9439 if (READ_EXTERNAL_STORAGE.equals(permission)) {
Jeff Sharkeyf5385772012-05-11 14:04:41 -07009440 if (mSettings.mReadExternalStorageEnforced != null) {
9441 return mSettings.mReadExternalStorageEnforced;
9442 } else {
9443 // if user hasn't defined, fall back to secure default
9444 return Secure.getInt(mContext.getContentResolver(),
9445 Secure.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT, 0) != 0;
9446 }
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009447 } else {
9448 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009449 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009450 }
Jeff Sharkeyf6f7f1d2012-06-12 17:12:08 -07009451
9452 public boolean isStorageLow() {
9453 final long token = Binder.clearCallingIdentity();
9454 try {
9455 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
9456 .getService(DeviceStorageMonitorService.SERVICE);
9457 return dsm.isMemoryLow();
9458 } finally {
9459 Binder.restoreCallingIdentity(token);
9460 }
9461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462}