blob: b5d0b604c22d53e7ada2056b25b9555ae9189329 [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;
Dianne Hackborn49237342009-08-27 20:08:01 -070056import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.pm.IPackageDataObserver;
58import android.content.pm.IPackageDeleteObserver;
59import android.content.pm.IPackageInstallObserver;
60import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080061import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.pm.IPackageStatsObserver;
63import android.content.pm.InstrumentationInfo;
64import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080065import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060067import android.content.pm.PackageParser;
Kenny Root27989422011-02-23 16:28:26 -080068import android.content.pm.PackageStats;
Kenny Root0e2c0f32011-04-15 17:50:10 -070069import android.content.pm.ParceledListSlice;
Jason parksa3cdaa52011-01-13 14:15:43 -060070import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080071import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.content.pm.ProviderInfo;
73import android.content.pm.ResolveInfo;
74import android.content.pm.ServiceInfo;
75import android.content.pm.Signature;
Amith Yamasani0b285492011-04-14 17:35:23 -070076import android.content.pm.UserInfo;
Kenny Root5ab21572011-07-27 11:11:19 -070077import android.content.pm.ManifestDigest;
Kenny Root0aaa0d92011-09-12 16:42:55 -070078import android.content.pm.VerifierDeviceIdentity;
Kenny Root05ca4c92011-09-15 10:36:25 -070079import android.content.pm.VerifierInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.net.Uri;
81import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070082import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -080084import android.os.Environment;
85import android.os.FileObserver;
86import android.os.FileUtils;
87import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080089import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070090import android.os.Looper;
91import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.os.ParcelFileDescriptor;
94import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -080095import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.os.ServiceManager;
97import android.os.SystemClock;
98import android.os.SystemProperties;
Amith Yamasani742a6712011-05-04 14:49:28 -070099import android.os.UserId;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800100import android.security.SystemKeyStore;
Kenny Root27989422011-02-23 16:28:26 -0800101import android.util.DisplayMetrics;
102import android.util.EventLog;
103import android.util.Log;
104import android.util.LogPrinter;
105import android.util.Slog;
106import android.util.SparseArray;
107import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.view.Display;
109import android.view.WindowManager;
110
111import java.io.File;
112import java.io.FileDescriptor;
113import java.io.FileInputStream;
114import java.io.FileNotFoundException;
115import java.io.FileOutputStream;
116import java.io.FileReader;
117import java.io.FilenameFilter;
118import java.io.IOException;
119import java.io.InputStream;
120import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800121import java.security.NoSuchAlgorithmException;
Kenny Root05ca4c92011-09-15 10:36:25 -0700122import java.security.PublicKey;
123import java.security.cert.CertificateException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800124import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import java.util.ArrayList;
126import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700127import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128import java.util.Collections;
129import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800130import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131import java.util.Enumeration;
132import 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;
139import java.util.zip.ZipEntry;
140import java.util.zip.ZipFile;
141import java.util.zip.ZipOutputStream;
142
Kenny Root66269ea2011-07-12 14:14:01 -0700143import libcore.io.ErrnoException;
Kenny Root3f99afc2012-04-14 10:13:10 -0700144import libcore.io.IoUtils;
Kenny Root66269ea2011-07-12 14:14:01 -0700145import libcore.io.Libcore;
146
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700147/**
148 * Keep track of all those .apks everywhere.
149 *
150 * This is very central to the platform's security; please run the unit
151 * tests whenever making modifications here:
152 *
153mmm frameworks/base/tests/AndroidTests
154adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
155adb 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 -0700156 *
157 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700158 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700159public class PackageManagerService extends IPackageManager.Stub {
160 static final String TAG = "PackageManager";
161 static final boolean DEBUG_SETTINGS = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final boolean DEBUG_PREFERRED = false;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700163 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800164 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800165 private static final boolean DEBUG_REMOVE = false;
166 private static final boolean DEBUG_SHOW_INFO = false;
167 private static final boolean DEBUG_PACKAGE_INFO = false;
168 private static final boolean DEBUG_INTENT_MATCHING = false;
169 private static final boolean DEBUG_PACKAGE_SCANNING = false;
170 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
Kenny Root05ca4c92011-09-15 10:36:25 -0700171 private static final boolean DEBUG_VERIFY = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400174 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700175 private static final int NFC_UID = Process.NFC_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 private static final boolean GET_CERTIFICATES = true;
178
179 private static final int REMOVE_EVENTS =
180 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
181 private static final int ADD_EVENTS =
182 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
183
184 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800185 // Suffix used during package installation when copying/moving
186 // package apks to install directory.
187 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 static final int SCAN_MONITOR = 1<<0;
190 static final int SCAN_NO_DEX = 1<<1;
191 static final int SCAN_FORCE_DEX = 1<<2;
192 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800193 static final int SCAN_NEW_INSTALL = 1<<4;
194 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700195 static final int SCAN_UPDATE_TIME = 1<<6;
Dianne Hackborn661cd522011-08-22 00:26:20 -0700196 static final int SCAN_DEFER_DEX = 1<<7;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700198 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700199
Kenny Root5ab21572011-07-27 11:11:19 -0700200 /**
201 * Whether verification is enabled by default.
202 */
Brett Chabotae05e862011-08-24 18:38:26 -0700203 // STOPSHIP: change this to true
204 private static final boolean DEFAULT_VERIFY_ENABLE = false;
Kenny Root5ab21572011-07-27 11:11:19 -0700205
206 /**
207 * The default maximum time to wait for the verification agent to return in
208 * milliseconds.
209 */
210 private static final long DEFAULT_VERIFICATION_TIMEOUT = 60 * 1000;
211
Kenny Root11128572010-10-11 10:51:32 -0700212 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
213
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800214 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700215 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800216 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700217
Kenny Root05ca4c92011-09-15 10:36:25 -0700218 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
219
Kenny Root85387d72010-08-26 10:13:11 -0700220 private static final String LIB_DIR_NAME = "lib";
221
Kenny Rootc78a8072010-07-27 15:18:38 -0700222 static final String mTempContainerPrefix = "smdl2tmp";
223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
225 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700226 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227
Dianne Hackborn851a5412009-05-08 12:06:44 -0700228 final int mSdkVersion = Build.VERSION.SDK_INT;
229 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
230 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 final Context mContext;
233 final boolean mFactoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700234 final boolean mOnlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700235 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 final DisplayMetrics mMetrics;
237 final int mDefParseFlags;
238 final String[] mSeparateProcesses;
239
240 // This is where all application persistent data goes.
241 final File mAppDataDir;
242
Amith Yamasani0b285492011-04-14 17:35:23 -0700243 // This is where all application persistent data goes for secondary users.
244 final File mUserAppDataDir;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // This is the object monitoring the framework dir.
247 final FileObserver mFrameworkInstallObserver;
248
249 // This is the object monitoring the system app dir.
250 final FileObserver mSystemInstallObserver;
251
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700252 // This is the object monitoring the system app dir.
253 final FileObserver mVendorInstallObserver;
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 // This is the object monitoring mAppInstallDir.
256 final FileObserver mAppInstallObserver;
257
258 // This is the object monitoring mDrmAppPrivateInstallDir.
259 final FileObserver mDrmAppInstallObserver;
260
261 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
262 // LOCK HELD. Can be called with mInstallLock held.
263 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 final File mFrameworkDir;
266 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700267 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700269 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
272 // apps.
273 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // Lock for state used when installing and doing other long running
278 // operations. Methods that must be called with this lock held have
279 // the prefix "LI".
280 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 // These are the directories in the 3rd party applications installed dir
283 // that we have currently loaded packages from. Keys are the application's
284 // installed zip file (absolute codePath), and values are Package.
285 final HashMap<String, PackageParser.Package> mAppDirs =
286 new HashMap<String, PackageParser.Package>();
287
288 // Information for the parser to write more useful error messages.
289 File mScanningPath;
290 int mLastScanError;
291
292 final int[] mOutPermissions = new int[3];
293
294 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 // Keys are String (package name), values are Package. This also serves
297 // as the lock for the global state. Methods that must be called with
298 // this lock held have the prefix "LP".
299 final HashMap<String, PackageParser.Package> mPackages =
300 new HashMap<String, PackageParser.Package>();
301
302 final Settings mSettings;
303 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304
305 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
306 int[] mGlobalGids;
307
308 // These are the built-in uid -> permission mappings that were read from the
309 // etc/permissions.xml file.
310 final SparseArray<HashSet<String>> mSystemPermissions =
311 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 // These are the built-in shared libraries that were read from the
314 // etc/permissions.xml file.
315 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800316
Dianne Hackborn49237342009-08-27 20:08:01 -0700317 // Temporary for building the final shared libraries for an .apk.
318 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800319
Dianne Hackborn49237342009-08-27 20:08:01 -0700320 // These are the features this devices supports that were read from the
321 // etc/permissions.xml file.
322 final HashMap<String, FeatureInfo> mAvailableFeatures =
323 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 // All available activities, for your resolving pleasure.
326 final ActivityIntentResolver mActivities =
327 new ActivityIntentResolver();
328
329 // All available receivers, for your resolving pleasure.
330 final ActivityIntentResolver mReceivers =
331 new ActivityIntentResolver();
332
333 // All available services, for your resolving pleasure.
334 final ServiceIntentResolver mServices = new ServiceIntentResolver();
335
336 // Keys are String (provider class name), values are Provider.
337 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
338 new HashMap<ComponentName, PackageParser.Provider>();
339
340 // Mapping from provider base names (first directory in content URI codePath)
341 // to the provider information.
342 final HashMap<String, PackageParser.Provider> mProviders =
343 new HashMap<String, PackageParser.Provider>();
344
345 // Mapping from instrumentation class names to info about them.
346 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
347 new HashMap<ComponentName, PackageParser.Instrumentation>();
348
349 // Mapping from permission names to info about them.
350 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
351 new HashMap<String, PackageParser.PermissionGroup>();
352
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800353 // Packages whose data we have transfered into another package, thus
354 // should no longer exist.
355 final HashSet<String> mTransferedPackages = new HashSet<String>();
356
Dianne Hackborn854060af2009-07-09 18:14:31 -0700357 // Broadcast actions that are only available to the system.
358 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800359
Kenny Root5ab21572011-07-27 11:11:19 -0700360 /** List of packages waiting for verification. */
Kenny Root05ca4c92011-09-15 10:36:25 -0700361 final SparseArray<PackageVerificationState> mPendingVerification
362 = new SparseArray<PackageVerificationState>();
Kenny Root5ab21572011-07-27 11:11:19 -0700363
Dianne Hackborn661cd522011-08-22 00:26:20 -0700364 final ArrayList<PackageParser.Package> mDeferredDexOpt =
365 new ArrayList<PackageParser.Package>();
366
Kenny Root5ab21572011-07-27 11:11:19 -0700367 /** Token for keys in mPendingVerification. */
368 private int mPendingVerificationToken = 0;
369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 boolean mSystemReady;
371 boolean mSafeMode;
372 boolean mHasSystemUidErrors;
373
374 ApplicationInfo mAndroidApplication;
375 final ActivityInfo mResolveActivity = new ActivityInfo();
376 final ResolveInfo mResolveInfo = new ResolveInfo();
377 ComponentName mResolveComponentName;
378 PackageParser.Package mPlatformPackage;
379
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700380 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800381 final HashMap<String, ArrayList<String>> mPendingBroadcasts
382 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800383 // Service Connection to remote media container service to copy
384 // package uri's from external media onto secure containers
385 // or internal storage.
386 private IMediaContainerService mContainerService = null;
387
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700388 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800389 static final int MCS_BOUND = 3;
390 static final int END_COPY = 4;
391 static final int INIT_COPY = 5;
392 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800393 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800394 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800395 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800396 static final int MCS_RECONNECT = 10;
397 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700398 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700399 static final int WRITE_SETTINGS = 13;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700400 static final int WRITE_PACKAGE_RESTRICTIONS = 14;
Kenny Root5ab21572011-07-27 11:11:19 -0700401 static final int PACKAGE_VERIFIED = 15;
402 static final int CHECK_PENDING_VERIFICATION = 16;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700403
404 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800405
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700406 // Delay time in millisecs
407 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800408
Amith Yamasani13593602012-03-22 16:16:17 -0700409 static UserManager sUserManager;
Amith Yamasani0b285492011-04-14 17:35:23 -0700410
Amith Yamasani483f3b02012-03-13 16:08:00 -0700411 // Stores a list of users whose package restrictions file needs to be updated
412 private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
413
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800414 final private DefaultContainerConnection mDefContainerConn =
415 new DefaultContainerConnection();
416 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800417 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800418 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800419 IMediaContainerService imcs =
420 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800421 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800422 }
423
424 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800425 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800426 }
427 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700428
Christopher Tate1bb69062010-02-19 17:02:12 -0800429 // Recordkeeping of restore-after-install operations that are currently in flight
430 // between the Package Manager and the Backup Manager
431 class PostInstallData {
432 public InstallArgs args;
433 public PackageInstalledInfo res;
434
435 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
436 args = _a;
437 res = _r;
438 }
439 };
440 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
441 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
442
Kenny Root05ca4c92011-09-15 10:36:25 -0700443 private final String mRequiredVerifierPackage;
444
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700445 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800446 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800447 final ArrayList<HandlerParams> mPendingInstalls =
448 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800449
450 private boolean connectToService() {
451 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
452 " DefaultContainerService");
453 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700454 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800455 if (mContext.bindService(service, mDefContainerConn,
456 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700457 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800458 mBound = true;
459 return true;
460 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700461 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800462 return false;
463 }
464
465 private void disconnectService() {
466 mContainerService = null;
467 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700468 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800469 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700470 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800471 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800472
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700473 PackageHandler(Looper looper) {
474 super(looper);
475 }
Dianne Hackborn7d608422011-08-07 16:24:18 -0700476
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700477 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700478 try {
479 doHandleMessage(msg);
480 } finally {
481 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
482 }
483 }
484
485 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700486 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800487 case INIT_COPY: {
Kenny Root5ab21572011-07-27 11:11:19 -0700488 if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800489 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800490 int idx = mPendingInstalls.size();
Kenny Root5ab21572011-07-27 11:11:19 -0700491 if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800492 // If a bind was already initiated we dont really
493 // need to do anything. The pending install
494 // will be processed later on.
495 if (!mBound) {
496 // If this is the only one pending we might
497 // have to bind to the service again.
498 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800499 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800500 params.serviceError();
501 return;
502 } else {
503 // Once we bind to the service, the first
504 // pending request will be processed.
505 mPendingInstalls.add(idx, params);
506 }
507 } else {
508 mPendingInstalls.add(idx, params);
509 // Already bound to the service. Just make
510 // sure we trigger off processing the first request.
511 if (idx == 0) {
512 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800513 }
514 }
515 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800516 }
517 case MCS_BOUND: {
Kenny Root5ab21572011-07-27 11:11:19 -0700518 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800519 if (msg.obj != null) {
520 mContainerService = (IMediaContainerService) msg.obj;
521 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800522 if (mContainerService == null) {
523 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800524 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800525 for (HandlerParams params : mPendingInstalls) {
526 mPendingInstalls.remove(0);
527 // Indicate service bind error
528 params.serviceError();
529 }
530 mPendingInstalls.clear();
531 } else if (mPendingInstalls.size() > 0) {
532 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800533 if (params != null) {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700534 if (params.startCopy()) {
535 // We are done... look for more work or to
536 // go idle.
537 if (DEBUG_SD_INSTALL) Log.i(TAG,
538 "Checking for more work or unbind...");
539 // Delete pending install
540 if (mPendingInstalls.size() > 0) {
541 mPendingInstalls.remove(0);
542 }
543 if (mPendingInstalls.size() == 0) {
544 if (mBound) {
545 if (DEBUG_SD_INSTALL) Log.i(TAG,
546 "Posting delayed MCS_UNBIND");
547 removeMessages(MCS_UNBIND);
548 Message ubmsg = obtainMessage(MCS_UNBIND);
549 // Unbind after a little delay, to avoid
550 // continual thrashing.
551 sendMessageDelayed(ubmsg, 10000);
552 }
553 } else {
554 // There are more pending requests in queue.
555 // Just post MCS_BOUND message to trigger processing
556 // of next pending install.
557 if (DEBUG_SD_INSTALL) Log.i(TAG,
558 "Posting MCS_BOUND for next woek");
559 mHandler.sendEmptyMessage(MCS_BOUND);
560 }
561 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800562 }
563 } else {
564 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800565 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800566 }
567 break;
568 }
Kenny Root5ab21572011-07-27 11:11:19 -0700569 case MCS_RECONNECT: {
570 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800571 if (mPendingInstalls.size() > 0) {
572 if (mBound) {
573 disconnectService();
574 }
575 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800576 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800577 for (HandlerParams params : mPendingInstalls) {
578 mPendingInstalls.remove(0);
579 // Indicate service bind error
580 params.serviceError();
581 }
582 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800583 }
584 }
585 break;
586 }
Kenny Root5ab21572011-07-27 11:11:19 -0700587 case MCS_UNBIND: {
Dianne Hackborn7d608422011-08-07 16:24:18 -0700588 // If there is no actual work left, then time to unbind.
Kenny Root5ab21572011-07-27 11:11:19 -0700589 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
590
591 if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800592 if (mBound) {
Kenny Root5ab21572011-07-27 11:11:19 -0700593 if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
594
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800595 disconnectService();
596 }
Kenny Root5ab21572011-07-27 11:11:19 -0700597 } else if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800598 // There are more pending requests in queue.
599 // Just post MCS_BOUND message to trigger processing
600 // of next pending install.
601 mHandler.sendEmptyMessage(MCS_BOUND);
602 }
Kenny Root5ab21572011-07-27 11:11:19 -0700603
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800604 break;
605 }
606 case MCS_GIVE_UP: {
Kenny Root5ab21572011-07-27 11:11:19 -0700607 if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700608 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800609 break;
610 }
Kenny Root5ab21572011-07-27 11:11:19 -0700611 case SEND_PENDING_BROADCAST: {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800612 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700613 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700614 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700615 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700616 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700617 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800618 if (mPendingBroadcasts == null) {
619 return;
620 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700621 size = mPendingBroadcasts.size();
622 if (size <= 0) {
623 // Nothing to be done. Just return
624 return;
625 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800626 packages = new String[size];
627 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700628 uids = new int[size];
Andy McFadden2f362292012-01-20 14:43:38 -0800629 Iterator<Map.Entry<String, ArrayList<String>>>
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800630 it = mPendingBroadcasts.entrySet().iterator();
631 int i = 0;
632 while (it.hasNext() && i < size) {
Andy McFadden2f362292012-01-20 14:43:38 -0800633 Map.Entry<String, ArrayList<String>> ent = it.next();
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800634 packages[i] = ent.getKey();
635 components[i] = ent.getValue();
636 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -0700637 uids[i] = (ps != null) ? ps.appId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800638 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700639 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800640 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700641 mPendingBroadcasts.clear();
642 }
643 // Send broadcasts
644 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700645 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700646 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700647 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700648 break;
649 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800650 case START_CLEANING_PACKAGE: {
651 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700652 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800653 synchronized (mPackages) {
654 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
655 mSettings.mPackagesToBeCleaned.add(packageName);
656 }
657 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700658 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800659 startCleaningPackages();
660 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800661 case POST_INSTALL: {
662 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
663 PostInstallData data = mRunningInstalls.get(msg.arg1);
664 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700665 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800666
667 if (data != null) {
668 InstallArgs args = data.args;
669 PackageInstalledInfo res = data.res;
670
671 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700672 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800673 Bundle extras = new Bundle(1);
674 extras.putInt(Intent.EXTRA_UID, res.uid);
675 final boolean update = res.removedInfo.removedPackage != null;
676 if (update) {
677 extras.putBoolean(Intent.EXTRA_REPLACING, true);
678 }
679 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
680 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700681 extras, null, null, UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800682 if (update) {
683 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
684 res.pkg.applicationInfo.packageName,
Amith Yamasani13593602012-03-22 16:16:17 -0700685 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800686 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
687 null, null,
Amith Yamasani13593602012-03-22 16:16:17 -0700688 res.pkg.applicationInfo.packageName, null,
689 UserId.USER_ALL);
Christopher Tate1bb69062010-02-19 17:02:12 -0800690 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700691 if (res.removedInfo.args != null) {
692 // Remove the replaced package's older resources safely now
693 deleteOld = true;
694 }
695 }
696 // Force a gc to clear up things
697 Runtime.getRuntime().gc();
698 // We delete after a gc for applications on sdcard.
699 if (deleteOld) {
700 synchronized (mInstallLock) {
701 res.removedInfo.args.doPostDeleteLI(true);
702 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800703 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800704 if (args.observer != null) {
705 try {
706 args.observer.packageInstalled(res.name, res.returnCode);
707 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800708 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800709 }
710 }
711 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800712 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800713 }
714 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700715 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700716 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
717 boolean reportStatus = msg.arg1 == 1;
718 boolean doGc = msg.arg2 == 1;
719 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
720 if (doGc) {
721 // Force a gc to clear up stale containers.
722 Runtime.getRuntime().gc();
723 }
724 if (msg.obj != null) {
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700725 @SuppressWarnings("unchecked")
Kenny Root6dceb882012-04-12 14:23:49 -0700726 Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700727 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
728 // Unload containers
729 unloadAllContainers(args);
730 }
731 if (reportStatus) {
732 try {
733 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
734 PackageHelper.getMountService().finishMediaUpdate();
735 } catch (RemoteException e) {
736 Log.e(TAG, "MountService not running?");
737 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700738 }
739 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700740 case WRITE_SETTINGS: {
741 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
742 synchronized (mPackages) {
743 removeMessages(WRITE_SETTINGS);
Amith Yamasani483f3b02012-03-13 16:08:00 -0700744 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
Kenny Root447106f2011-03-23 11:00:15 -0700745 mSettings.writeLPr();
Amith Yamasani483f3b02012-03-13 16:08:00 -0700746 mDirtyUsers.clear();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700747 }
748 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
749 } break;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700750 case WRITE_PACKAGE_RESTRICTIONS: {
Dianne Hackborne7f97212011-02-24 14:40:20 -0800751 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
752 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -0700753 removeMessages(WRITE_PACKAGE_RESTRICTIONS);
754 for (int userId : mDirtyUsers) {
755 mSettings.writePackageRestrictionsLPr(userId);
756 }
757 mDirtyUsers.clear();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800758 }
759 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
760 } break;
Kenny Root5ab21572011-07-27 11:11:19 -0700761 case CHECK_PENDING_VERIFICATION: {
762 final int verificationId = msg.arg1;
Kenny Root05ca4c92011-09-15 10:36:25 -0700763 final PackageVerificationState state = mPendingVerification.get(verificationId);
Kenny Root5ab21572011-07-27 11:11:19 -0700764
Kenny Root05ca4c92011-09-15 10:36:25 -0700765 if (state != null) {
766 final InstallArgs args = state.getInstallArgs();
Kenny Roota503a0f2011-10-03 14:45:28 -0700767 Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
Kenny Root5ab21572011-07-27 11:11:19 -0700768 mPendingVerification.remove(verificationId);
769
770 int ret = PackageManager.INSTALL_FAILED_VERIFICATION_TIMEOUT;
771 processPendingInstall(args, ret);
772
773 mHandler.sendEmptyMessage(MCS_UNBIND);
774 }
775
776 break;
777 }
778 case PACKAGE_VERIFIED: {
779 final int verificationId = msg.arg1;
Kenny Root5ab21572011-07-27 11:11:19 -0700780
Kenny Root05ca4c92011-09-15 10:36:25 -0700781 final PackageVerificationState state = mPendingVerification.get(verificationId);
782 if (state == null) {
Kenny Roota503a0f2011-10-03 14:45:28 -0700783 Slog.w(TAG, "Invalid verification token " + verificationId + " received");
Kenny Root5ab21572011-07-27 11:11:19 -0700784 break;
785 }
786
Kenny Root05ca4c92011-09-15 10:36:25 -0700787 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
Kenny Root5ab21572011-07-27 11:11:19 -0700788
Kenny Root05ca4c92011-09-15 10:36:25 -0700789 state.setVerifierResponse(response.callerUid, response.code);
790
791 if (state.isVerificationComplete()) {
792 mPendingVerification.remove(verificationId);
793
794 final InstallArgs args = state.getInstallArgs();
795
796 int ret;
797 if (state.isInstallAllowed()) {
798 ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
799 try {
800 ret = args.copyApk(mContainerService, true);
801 } catch (RemoteException e) {
802 Slog.e(TAG, "Could not contact the ContainerService");
803 }
804 } else {
805 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
Kenny Root5ab21572011-07-27 11:11:19 -0700806 }
Kenny Root05ca4c92011-09-15 10:36:25 -0700807
808 processPendingInstall(args, ret);
809
810 mHandler.sendEmptyMessage(MCS_UNBIND);
Kenny Root5ab21572011-07-27 11:11:19 -0700811 }
812
Kenny Root5ab21572011-07-27 11:11:19 -0700813 break;
814 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700815 }
816 }
817 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800818
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700819 void scheduleWriteSettingsLocked() {
820 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
821 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
822 }
823 }
Amith Yamasani483f3b02012-03-13 16:08:00 -0700824
825 void scheduleWritePackageRestrictionsLocked(int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -0700826 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -0700827 mDirtyUsers.add(userId);
828 if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
829 mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800830 }
831 }
832
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700833 public static final IPackageManager main(Context context, boolean factoryTest,
834 boolean onlyCore) {
835 PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 ServiceManager.addService("package", m);
837 return m;
838 }
839
840 static String[] splitString(String str, char sep) {
841 int count = 1;
842 int i = 0;
843 while ((i=str.indexOf(sep, i)) >= 0) {
844 count++;
845 i++;
846 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 String[] res = new String[count];
849 i=0;
850 count = 0;
851 int lastI=0;
852 while ((i=str.indexOf(sep, i)) >= 0) {
853 res[count] = str.substring(lastI, i);
854 count++;
855 i++;
856 lastI = i;
857 }
858 res[count] = str.substring(lastI, str.length());
859 return res;
860 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800861
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700862 public PackageManagerService(Context context, boolean factoryTest, boolean onlyCore) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800863 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800867 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 mContext = context;
871 mFactoryTest = factoryTest;
Dianne Hackbornd2509fd2011-09-12 12:29:43 -0700872 mOnlyCore = onlyCore;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700873 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 mMetrics = new DisplayMetrics();
875 mSettings = new Settings();
Kenny Root447106f2011-03-23 11:00:15 -0700876 mSettings.addSharedUserLPw("android.uid.system",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
Dianne Hackborn21fbd1f2012-02-10 10:38:10 -0800878 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
879 mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
880 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881
882 String separateProcesses = SystemProperties.get("debug.separate_processes");
883 if (separateProcesses != null && separateProcesses.length() > 0) {
884 if ("*".equals(separateProcesses)) {
885 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
886 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800887 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 } else {
889 mDefParseFlags = 0;
890 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800891 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 + separateProcesses);
893 }
894 } else {
895 mDefParseFlags = 0;
896 mSeparateProcesses = null;
897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800898
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700899 mInstaller = new Installer();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900
901 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
902 Display d = wm.getDefaultDisplay();
903 d.getMetrics(mMetrics);
904
905 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -0700906 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 synchronized (mPackages) {
908 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700909 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 File dataDir = Environment.getDataDirectory();
912 mAppDataDir = new File(dataDir, "data");
Amith Yamasani0b285492011-04-14 17:35:23 -0700913 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
915
Amith Yamasani13593602012-03-22 16:16:17 -0700916 sUserManager = new UserManager(mInstaller, mUserAppDataDir);
Amith Yamasani0b285492011-04-14 17:35:23 -0700917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 readPermissions();
919
Amith Yamasani483f3b02012-03-13 16:08:00 -0700920 mRestoredSettings = mSettings.readLPw(getUsers());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800922
923 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800925
Suchi Amalapurapudaec1722010-01-14 21:25:16 -0800926 // Set flag to monitor and not change apk file paths when
927 // scanning install directories.
Dianne Hackborn661cd522011-08-22 00:26:20 -0700928 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700929 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800930 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800931 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700937 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800938
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700939 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800940
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700941 /**
942 * Out of paranoia, ensure that everything in the boot class
943 * path has been dexed.
944 */
945 String bootClassPath = System.getProperty("java.boot.class.path");
946 if (bootClassPath != null) {
947 String[] paths = splitString(bootClassPath, ':');
948 for (int i=0; i<paths.length; i++) {
949 try {
950 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
951 libFiles.add(paths[i]);
952 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
953 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700955 } catch (FileNotFoundException e) {
956 Slog.w(TAG, "Boot class path not found: " + paths[i]);
957 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -0700958 Slog.w(TAG, "Cannot dexopt " + paths[i] + "; is it an APK or JAR? "
959 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700962 } else {
963 Slog.w(TAG, "No BOOTCLASSPATH found!");
964 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800965
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700966 /**
967 * Also ensure all external libraries have had dexopt run on them.
968 */
969 if (mSharedLibraries.size() > 0) {
970 Iterator<String> libs = mSharedLibraries.values().iterator();
971 while (libs.hasNext()) {
972 String lib = libs.next();
973 try {
974 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
975 libFiles.add(lib);
976 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
977 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700979 } catch (FileNotFoundException e) {
980 Slog.w(TAG, "Library not found: " + lib);
981 } catch (IOException e) {
Kenny Rootfec5e752011-09-23 10:09:58 -0700982 Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
983 + e.getMessage());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
985 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700986 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800987
Jeff Brown5d6d90f2011-07-11 13:04:53 -0700988 // Gross hack for now: we know this file doesn't contain any
989 // code, so don't dexopt it to avoid the resulting log spew.
990 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
991
992 /**
993 * And there are a number of commands implemented in Java, which
994 * we currently need to do the dexopt on so that they can be
995 * run from a non-root shell.
996 */
997 String[] frameworkFiles = mFrameworkDir.list();
998 if (frameworkFiles != null) {
999 for (int i=0; i<frameworkFiles.length; i++) {
1000 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
1001 String path = libPath.getPath();
1002 // Skip the file if we alrady did it.
1003 if (libFiles.contains(path)) {
1004 continue;
1005 }
1006 // Skip the file if it is not a type we want to dexopt.
1007 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
1008 continue;
1009 }
1010 try {
1011 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
1012 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
1013 didDexOpt = true;
1014 }
1015 } catch (FileNotFoundException e) {
1016 Slog.w(TAG, "Jar not found: " + path);
1017 } catch (IOException e) {
1018 Slog.w(TAG, "Exception reading jar: " + path, e);
1019 }
1020 }
1021 }
1022
1023 if (didDexOpt) {
1024 // If we had to do a dexopt of one of the previous
1025 // things, then something on the system has changed.
1026 // Consider this significant, and wipe away all other
1027 // existing dexopt files to ensure we don't leave any
1028 // dangling around.
1029 String[] files = mDalvikCacheDir.list();
1030 if (files != null) {
1031 for (int i=0; i<files.length; i++) {
1032 String fn = files[i];
1033 if (fn.startsWith("data@app@")
1034 || fn.startsWith("data@app-private@")) {
1035 Slog.i(TAG, "Pruning dalvik file: " + fn);
1036 (new File(mDalvikCacheDir, fn)).delete();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001037 }
1038 }
1039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001041
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001042 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 mFrameworkInstallObserver = new AppDirObserver(
1044 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
1045 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001046 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
1047 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001048 scanMode | SCAN_NO_DEX, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001049
1050 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
1052 mSystemInstallObserver = new AppDirObserver(
1053 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
1054 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -07001055 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001056 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001057
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001058 // Collect all vendor packages.
1059 mVendorAppDir = new File("/vendor/app");
1060 mVendorInstallObserver = new AppDirObserver(
1061 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
1062 mVendorInstallObserver.startWatching();
1063 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001064 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07001065
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001066 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
1067 mInstaller.moveFiles();
1068
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001069 // Prune any system packages that no longer exist.
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001070 if (!mOnlyCore) {
1071 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
1072 while (psit.hasNext()) {
1073 PackageSetting ps = psit.next();
1074 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
1075 && !mPackages.containsKey(ps.name)
1076 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
1077 psit.remove();
1078 String msg = "System package " + ps.name
1079 + " no longer exists; wiping its data";
1080 reportSettingsProblem(Log.WARN, msg);
1081 mInstaller.remove(ps.name, 0);
Amith Yamasani13593602012-03-22 16:16:17 -07001082 sUserManager.removePackageForAllUsers(ps.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001083 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08001084 }
1085 }
1086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 mAppInstallDir = new File(dataDir, "app");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001089 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 //clean up list
1091 for(int i = 0; i < deletePkgsList.size(); i++) {
1092 //clean up here
1093 cleanupInstallFailedPackage(deletePkgsList.get(i));
1094 }
1095 //delete tmp files
1096 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001097
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07001098 if (!mOnlyCore) {
1099 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
1100 SystemClock.uptimeMillis());
1101 mAppInstallObserver = new AppDirObserver(
1102 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1103 mAppInstallObserver.startWatching();
1104 scanDirLI(mAppInstallDir, 0, scanMode, 0);
1105
1106 mDrmAppInstallObserver = new AppDirObserver(
1107 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1108 mDrmAppInstallObserver.startWatching();
1109 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1110 scanMode, 0);
1111 } else {
1112 mAppInstallObserver = null;
1113 mDrmAppInstallObserver = null;
1114 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001116 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001118 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1120 + " seconds");
1121
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001122 // If the platform SDK has changed since the last time we booted,
1123 // we need to re-grant app permission to catch any new ones that
1124 // appear. This is really a hack, and means that apps can in some
1125 // cases get permissions that the user didn't initially explicitly
1126 // allow... it would be nice to have some better way to handle
1127 // this situation.
1128 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1129 != mSdkVersion;
1130 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1131 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1132 + "; regranting permissions for internal storage");
1133 mSettings.mInternalSdkPlatform = mSdkVersion;
1134
Dianne Hackborne639da72012-02-21 15:11:13 -08001135 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
1136 | (regrantPermissions
1137 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
1138 : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139
Dianne Hackborn04505102012-02-29 12:34:04 -08001140 // Verify that all of the preferred activity components actually
1141 // exist. It is possible for applications to be updated and at
1142 // that point remove a previously declared activity component that
1143 // had been set as a preferred activity. We try to clean this up
1144 // the next time we encounter that preferred activity, but it is
1145 // possible for the user flow to never be able to return to that
1146 // situation so here we do a sanity check to make sure we haven't
1147 // left any junk around.
1148 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
1149 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
1150 if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
1151 removed.add(pa);
1152 }
1153 }
1154 for (int i=0; i<removed.size(); i++) {
1155 PreferredActivity pa = removed.get(i);
1156 Slog.w(TAG, "Removing dangling preferred activity: "
1157 + pa.mPref.mComponent);
1158 mSettings.mPreferredActivities.removeFilter(pa);
1159 }
1160
Kenny Root447106f2011-03-23 11:00:15 -07001161 // can downgrade to reader
1162 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001164 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 // Now after opening every single application zip, make sure they
1168 // are all flushed. Not really needed, but keeps things nice and
1169 // tidy.
1170 Runtime.getRuntime().gc();
Kenny Root05ca4c92011-09-15 10:36:25 -07001171
1172 mRequiredVerifierPackage = getRequiredVerifierLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 } // synchronized (mPackages)
1174 } // synchronized (mInstallLock)
1175 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001176
Dianne Hackborn58f42a52011-10-10 13:46:34 -07001177 public boolean isFirstBoot() {
1178 return !mRestoredSettings;
1179 }
1180
Kenny Root05ca4c92011-09-15 10:36:25 -07001181 private String getRequiredVerifierLPr() {
1182 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
1183 final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
Amith Yamasani483f3b02012-03-13 16:08:00 -07001184 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07001185
1186 String requiredVerifier = null;
1187
1188 final int N = receivers.size();
1189 for (int i = 0; i < N; i++) {
1190 final ResolveInfo info = receivers.get(i);
1191
1192 if (info.activityInfo == null) {
1193 continue;
1194 }
1195
1196 final String packageName = info.activityInfo.packageName;
1197
1198 final PackageSetting ps = mSettings.mPackages.get(packageName);
1199 if (ps == null) {
1200 continue;
1201 }
1202
1203 if (!ps.grantedPermissions
1204 .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
1205 continue;
1206 }
1207
1208 if (requiredVerifier != null) {
1209 throw new RuntimeException("There can be only one required verifier");
1210 }
1211
1212 requiredVerifier = packageName;
1213 }
1214
1215 return requiredVerifier;
1216 }
1217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 @Override
1219 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1220 throws RemoteException {
1221 try {
1222 return super.onTransact(code, data, reply, flags);
1223 } catch (RuntimeException e) {
1224 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001225 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 }
1227 throw e;
1228 }
1229 }
1230
Dianne Hackborne6620b22010-01-22 14:46:21 -08001231 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001232 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001233 int retCode = mInstaller.remove(ps.name, 0);
1234 if (retCode < 0) {
1235 Slog.w(TAG, "Couldn't remove app data directory for package: "
1236 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 } else {
Amith Yamasani13593602012-03-22 16:16:17 -07001238 sUserManager.removePackageForAllUsers(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001240 if (ps.codePath != null) {
1241 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001242 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001243 }
1244 }
1245 if (ps.resourcePath != null) {
1246 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001247 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001248 }
1249 }
Kenny Root447106f2011-03-23 11:00:15 -07001250 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 }
1252
1253 void readPermissions() {
1254 // Read permissions from .../etc/permission directory.
1255 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1256 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001257 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 return;
1259 }
1260 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001261 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 return;
1263 }
1264
1265 // Iterate over the files in the directory and scan .xml files
1266 for (File f : libraryDir.listFiles()) {
1267 // We'll read platform.xml last
1268 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1269 continue;
1270 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001273 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 continue;
1275 }
1276 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001277 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 continue;
1279 }
1280
1281 readPermissionsFromXml(f);
1282 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1285 final File permFile = new File(Environment.getRootDirectory(),
1286 "etc/permissions/platform.xml");
1287 readPermissionsFromXml(permFile);
1288 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001289
1290 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 FileReader permReader = null;
1292 try {
1293 permReader = new FileReader(permFile);
1294 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001295 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 return;
1297 }
1298
1299 try {
1300 XmlPullParser parser = Xml.newPullParser();
1301 parser.setInput(permReader);
1302
1303 XmlUtils.beginDocument(parser, "permissions");
1304
1305 while (true) {
1306 XmlUtils.nextElement(parser);
1307 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1308 break;
1309 }
1310
1311 String name = parser.getName();
1312 if ("group".equals(name)) {
1313 String gidStr = parser.getAttributeValue(null, "gid");
1314 if (gidStr != null) {
1315 int gid = Integer.parseInt(gidStr);
1316 mGlobalGids = appendInt(mGlobalGids, gid);
1317 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001318 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 + parser.getPositionDescription());
1320 }
1321
1322 XmlUtils.skipCurrentTag(parser);
1323 continue;
1324 } else if ("permission".equals(name)) {
1325 String perm = parser.getAttributeValue(null, "name");
1326 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001327 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 + parser.getPositionDescription());
1329 XmlUtils.skipCurrentTag(parser);
1330 continue;
1331 }
1332 perm = perm.intern();
1333 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 } else if ("assign-permission".equals(name)) {
1336 String perm = parser.getAttributeValue(null, "name");
1337 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001338 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 + parser.getPositionDescription());
1340 XmlUtils.skipCurrentTag(parser);
1341 continue;
1342 }
1343 String uidStr = parser.getAttributeValue(null, "uid");
1344 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001345 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 + parser.getPositionDescription());
1347 XmlUtils.skipCurrentTag(parser);
1348 continue;
1349 }
1350 int uid = Process.getUidForName(uidStr);
1351 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001352 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 + uidStr + "\" at "
1354 + parser.getPositionDescription());
1355 XmlUtils.skipCurrentTag(parser);
1356 continue;
1357 }
1358 perm = perm.intern();
1359 HashSet<String> perms = mSystemPermissions.get(uid);
1360 if (perms == null) {
1361 perms = new HashSet<String>();
1362 mSystemPermissions.put(uid, perms);
1363 }
1364 perms.add(perm);
1365 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 } else if ("library".equals(name)) {
1368 String lname = parser.getAttributeValue(null, "name");
1369 String lfile = parser.getAttributeValue(null, "file");
1370 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001371 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 + parser.getPositionDescription());
1373 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001374 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 + parser.getPositionDescription());
1376 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001377 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001378 mSharedLibraries.put(lname, lfile);
1379 }
1380 XmlUtils.skipCurrentTag(parser);
1381 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001382
Dianne Hackborn49237342009-08-27 20:08:01 -07001383 } else if ("feature".equals(name)) {
1384 String fname = parser.getAttributeValue(null, "name");
1385 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001386 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001387 + parser.getPositionDescription());
1388 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001389 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001390 FeatureInfo fi = new FeatureInfo();
1391 fi.name = fname;
1392 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 XmlUtils.skipCurrentTag(parser);
1395 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 } else {
1398 XmlUtils.skipCurrentTag(parser);
1399 continue;
1400 }
1401
1402 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001403 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001405 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001407 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 }
1409 }
1410
1411 void readPermission(XmlPullParser parser, String name)
1412 throws IOException, XmlPullParserException {
1413
1414 name = name.intern();
1415
1416 BasePermission bp = mSettings.mPermissions.get(name);
1417 if (bp == null) {
1418 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1419 mSettings.mPermissions.put(name, bp);
1420 }
1421 int outerDepth = parser.getDepth();
1422 int type;
1423 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1424 && (type != XmlPullParser.END_TAG
1425 || parser.getDepth() > outerDepth)) {
1426 if (type == XmlPullParser.END_TAG
1427 || type == XmlPullParser.TEXT) {
1428 continue;
1429 }
1430
1431 String tagName = parser.getName();
1432 if ("group".equals(tagName)) {
1433 String gidStr = parser.getAttributeValue(null, "gid");
1434 if (gidStr != null) {
1435 int gid = Process.getGidForName(gidStr);
1436 bp.gids = appendInt(bp.gids, gid);
1437 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001438 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 + parser.getPositionDescription());
1440 }
1441 }
1442 XmlUtils.skipCurrentTag(parser);
1443 }
1444 }
1445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 static int[] appendInts(int[] cur, int[] add) {
1447 if (add == null) return cur;
1448 if (cur == null) return add;
1449 final int N = add.length;
1450 for (int i=0; i<N; i++) {
1451 cur = appendInt(cur, add[i]);
1452 }
1453 return cur;
1454 }
1455
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001456 static int[] removeInts(int[] cur, int[] rem) {
1457 if (rem == null) return cur;
1458 if (cur == null) return cur;
1459 final int N = rem.length;
1460 for (int i=0; i<N; i++) {
1461 cur = removeInt(cur, rem[i]);
1462 }
1463 return cur;
1464 }
1465
Amith Yamasani13593602012-03-22 16:16:17 -07001466 PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
1467 if (!sUserManager.exists(userId)) return null;
1468 PackageInfo pi;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001469 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1470 // The package has been uninstalled but has retained data and resources.
Amith Yamasani13593602012-03-22 16:16:17 -07001471 pi = PackageParser.generatePackageInfo(p, null, flags, 0, 0, null, false, 0, userId);
1472 } else {
1473 final PackageSetting ps = (PackageSetting) p.mExtras;
1474 if (ps == null) {
1475 return null;
1476 }
1477 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1478 pi = PackageParser.generatePackageInfo(p, gp.gids, flags,
1479 ps.firstInstallTime, ps.lastUpdateTime, gp.grantedPermissions,
1480 ps.getStopped(userId), ps.getEnabled(userId), userId);
1481 pi.applicationInfo.enabledSetting = ps.getEnabled(userId);
1482 pi.applicationInfo.enabled =
1483 pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_DEFAULT
1484 || pi.applicationInfo.enabledSetting == COMPONENT_ENABLED_STATE_ENABLED;
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001485 }
Amith Yamasani13593602012-03-22 16:16:17 -07001486 return pi;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 }
1488
Amith Yamasani483f3b02012-03-13 16:08:00 -07001489 @Override
1490 public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001491 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001492 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 synchronized (mPackages) {
1494 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001495 if (DEBUG_PACKAGE_INFO)
1496 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001498 return generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 }
1500 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001501 return generatePackageInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 }
1503 }
1504 return null;
1505 }
1506
Dianne Hackborn47096932010-02-11 15:57:09 -08001507 public String[] currentToCanonicalPackageNames(String[] names) {
1508 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001509 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001510 synchronized (mPackages) {
1511 for (int i=names.length-1; i>=0; i--) {
1512 PackageSetting ps = mSettings.mPackages.get(names[i]);
1513 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1514 }
1515 }
1516 return out;
1517 }
1518
1519 public String[] canonicalToCurrentPackageNames(String[] names) {
1520 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001521 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001522 synchronized (mPackages) {
1523 for (int i=names.length-1; i>=0; i--) {
1524 String cur = mSettings.mRenamedPackages.get(names[i]);
1525 out[i] = cur != null ? cur : names[i];
1526 }
1527 }
1528 return out;
1529 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07001530
1531 @Override
1532 public int getPackageUid(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001533 if (!sUserManager.exists(userId)) return -1;
Kenny Root447106f2011-03-23 11:00:15 -07001534 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 synchronized (mPackages) {
1536 PackageParser.Package p = mPackages.get(packageName);
1537 if(p != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001538 return UserId.getUid(userId, p.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 PackageSetting ps = mSettings.mPackages.get(packageName);
1541 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1542 return -1;
1543 }
1544 p = ps.pkg;
Amith Yamasani483f3b02012-03-13 16:08:00 -07001545 return p != null ? UserId.getUid(userId, p.applicationInfo.uid) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 }
1547 }
1548
1549 public int[] getPackageGids(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001550 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 synchronized (mPackages) {
1552 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001553 if (DEBUG_PACKAGE_INFO)
1554 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 if (p != null) {
1556 final PackageSetting ps = (PackageSetting)p.mExtras;
1557 final SharedUserSetting suid = ps.sharedUser;
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07001558 int[] gids = suid != null ? suid.gids : ps.gids;
1559
1560 // include GIDs for any unenforced permissions
1561 if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
1562 final BasePermission basePerm = mSettings.mPermissions.get(
1563 READ_EXTERNAL_STORAGE);
1564 gids = appendInts(gids, basePerm.gids);
1565 }
1566
1567 return gids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 }
1569 }
1570 // stupid thing to indicate an error.
1571 return new int[0];
1572 }
1573
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001574 static final PermissionInfo generatePermissionInfo(
1575 BasePermission bp, int flags) {
1576 if (bp.perm != null) {
1577 return PackageParser.generatePermissionInfo(bp.perm, flags);
1578 }
1579 PermissionInfo pi = new PermissionInfo();
1580 pi.name = bp.name;
1581 pi.packageName = bp.sourcePackage;
1582 pi.nonLocalizedLabel = bp.name;
1583 pi.protectionLevel = bp.protectionLevel;
1584 return pi;
1585 }
1586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001588 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 synchronized (mPackages) {
1590 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001591 if (p != null) {
1592 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 }
1594 return null;
1595 }
1596 }
1597
1598 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001599 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 synchronized (mPackages) {
1601 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1602 for (BasePermission p : mSettings.mPermissions.values()) {
1603 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001604 if (p.perm == null || p.perm.info.group == null) {
1605 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
1607 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001608 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1610 }
1611 }
1612 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 if (out.size() > 0) {
1615 return out;
1616 }
1617 return mPermissionGroups.containsKey(group) ? out : null;
1618 }
1619 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001622 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 synchronized (mPackages) {
1624 return PackageParser.generatePermissionGroupInfo(
1625 mPermissionGroups.get(name), flags);
1626 }
1627 }
1628
1629 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001630 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 synchronized (mPackages) {
1632 final int N = mPermissionGroups.size();
1633 ArrayList<PermissionGroupInfo> out
1634 = new ArrayList<PermissionGroupInfo>(N);
1635 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1636 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1637 }
1638 return out;
1639 }
1640 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001641
Amith Yamasani483f3b02012-03-13 16:08:00 -07001642 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
1643 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001644 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001646 if (ps != null) {
1647 if (ps.pkg == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001648 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags, userId);
Kenny Root447106f2011-03-23 11:00:15 -07001649 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 return pInfo.applicationInfo;
1651 }
1652 return null;
1653 }
Amith Yamasani13593602012-03-22 16:16:17 -07001654 return PackageParser.generateApplicationInfo(ps.pkg, flags, ps.getStopped(userId),
1655 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 }
1657 return null;
1658 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001659
Amith Yamasani483f3b02012-03-13 16:08:00 -07001660 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags,
1661 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001662 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001664 if (ps != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001665 PackageParser.Package pkg = new PackageParser.Package(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001666 if (ps.pkg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 ps.pkg = new PackageParser.Package(packageName);
1668 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001669 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1670 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1671 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
Amith Yamasani0b285492011-04-14 17:35:23 -07001672 ps.pkg.applicationInfo.dataDir =
1673 getDataPathForPackage(ps.pkg.packageName, 0).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001674 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
Amith Yamasani13593602012-03-22 16:16:17 -07001676 // ps.pkg.mSetEnabled = ps.getEnabled(userId);
1677 // ps.pkg.mSetStopped = ps.getStopped(userId);
1678 return generatePackageInfo(ps.pkg, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680 return null;
1681 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001682
Amith Yamasani483f3b02012-03-13 16:08:00 -07001683 @Override
1684 public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001685 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07001686 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 synchronized (mPackages) {
1688 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001689 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 TAG, "getApplicationInfo " + packageName
1691 + ": " + p);
1692 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07001693 PackageSetting ps = mSettings.mPackages.get(packageName);
1694 if (ps == null) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 // Note: isEnabledLP() does not apply here - always return info
Amith Yamasani13593602012-03-22 16:16:17 -07001696 return PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
1697 ps.getEnabled(userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 }
1699 if ("android".equals(packageName)||"system".equals(packageName)) {
1700 return mAndroidApplication;
1701 }
1702 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07001703 return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 }
1705 }
1706 return null;
1707 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001708
1709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1711 mContext.enforceCallingOrSelfPermission(
1712 android.Manifest.permission.CLEAR_APP_CACHE, null);
1713 // Queue up an async operation since clearing cache may take a little while.
1714 mHandler.post(new Runnable() {
1715 public void run() {
1716 mHandler.removeCallbacks(this);
1717 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001718 retCode = mInstaller.freeCache(freeStorageSize);
1719 if (retCode < 0) {
1720 Slog.w(TAG, "Couldn't clear application caches");
1721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 if (observer != null) {
1723 try {
1724 observer.onRemoveCompleted(null, (retCode >= 0));
1725 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001726 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
1728 }
1729 }
1730 });
1731 }
1732
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001733 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001734 mContext.enforceCallingOrSelfPermission(
1735 android.Manifest.permission.CLEAR_APP_CACHE, null);
1736 // Queue up an async operation since clearing cache may take a little while.
1737 mHandler.post(new Runnable() {
1738 public void run() {
1739 mHandler.removeCallbacks(this);
1740 int retCode = -1;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07001741 retCode = mInstaller.freeCache(freeStorageSize);
1742 if (retCode < 0) {
1743 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001744 }
1745 if(pi != null) {
1746 try {
1747 // Callback via pending intent
1748 int code = (retCode >= 0) ? 1 : 0;
1749 pi.sendIntent(null, code, null,
1750 null, null);
1751 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001752 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001753 }
1754 }
1755 }
1756 });
1757 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001758
Amith Yamasani483f3b02012-03-13 16:08:00 -07001759 @Override
1760 public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001761 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 synchronized (mPackages) {
1763 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001764
Kenny Root9718cf52011-02-23 16:45:26 -08001765 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001766 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001767 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1768 if (ps == null) return null;
1769 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1770 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
1772 if (mResolveComponentName.equals(component)) {
1773 return mResolveActivity;
1774 }
1775 }
1776 return null;
1777 }
1778
Amith Yamasani483f3b02012-03-13 16:08:00 -07001779 @Override
1780 public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001781 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 synchronized (mPackages) {
1783 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001784 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 TAG, "getReceiverInfo " + component + ": " + a);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001786 if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001787 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1788 if (ps == null) return null;
1789 return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId),
1790 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 }
1792 }
1793 return null;
1794 }
1795
Amith Yamasani483f3b02012-03-13 16:08:00 -07001796 @Override
1797 public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001798 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 synchronized (mPackages) {
1800 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001801 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 TAG, "getServiceInfo " + component + ": " + s);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001803 if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001804 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1805 if (ps == null) return null;
1806 return PackageParser.generateServiceInfo(s, flags, ps.getStopped(userId),
1807 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 }
1809 }
1810 return null;
1811 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001812
Amith Yamasani483f3b02012-03-13 16:08:00 -07001813 @Override
1814 public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07001815 if (!sUserManager.exists(userId)) return null;
Dianne Hackborn361199b2010-08-30 17:42:07 -07001816 synchronized (mPackages) {
1817 PackageParser.Provider p = mProvidersByComponent.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001818 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07001819 TAG, "getProviderInfo " + component + ": " + p);
Amith Yamasani483f3b02012-03-13 16:08:00 -07001820 if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
Amith Yamasani13593602012-03-22 16:16:17 -07001821 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
1822 if (ps == null) return null;
1823 return PackageParser.generateProviderInfo(p, flags, ps.getStopped(userId),
1824 ps.getEnabled(userId), userId);
Dianne Hackborn361199b2010-08-30 17:42:07 -07001825 }
1826 }
1827 return null;
1828 }
1829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 public String[] getSystemSharedLibraryNames() {
1831 Set<String> libSet;
1832 synchronized (mPackages) {
1833 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001834 int size = libSet.size();
1835 if (size > 0) {
1836 String[] libs = new String[size];
1837 libSet.toArray(libs);
1838 return libs;
1839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001841 return null;
1842 }
1843
1844 public FeatureInfo[] getSystemAvailableFeatures() {
1845 Collection<FeatureInfo> featSet;
1846 synchronized (mPackages) {
1847 featSet = mAvailableFeatures.values();
1848 int size = featSet.size();
1849 if (size > 0) {
1850 FeatureInfo[] features = new FeatureInfo[size+1];
1851 featSet.toArray(features);
1852 FeatureInfo fi = new FeatureInfo();
1853 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1854 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1855 features[size] = fi;
1856 return features;
1857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 }
1859 return null;
1860 }
1861
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001862 public boolean hasSystemFeature(String name) {
1863 synchronized (mPackages) {
1864 return mAvailableFeatures.containsKey(name);
1865 }
1866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001867
Amith Yamasani483f3b02012-03-13 16:08:00 -07001868 private void checkValidCaller(int uid, int userId) {
1869 if (UserId.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
1870 return;
1871
1872 throw new SecurityException("Caller uid=" + uid
1873 + " is not privileged to communicate with user=" + userId);
1874 }
1875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 public int checkPermission(String permName, String pkgName) {
1877 synchronized (mPackages) {
1878 PackageParser.Package p = mPackages.get(pkgName);
1879 if (p != null && p.mExtras != null) {
1880 PackageSetting ps = (PackageSetting)p.mExtras;
1881 if (ps.sharedUser != null) {
1882 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1883 return PackageManager.PERMISSION_GRANTED;
1884 }
1885 } else if (ps.grantedPermissions.contains(permName)) {
1886 return PackageManager.PERMISSION_GRANTED;
1887 }
1888 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07001889 if (!isPermissionEnforcedLocked(permName)) {
1890 return PackageManager.PERMISSION_GRANTED;
1891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
1893 return PackageManager.PERMISSION_DENIED;
1894 }
1895
1896 public int checkUidPermission(String permName, int uid) {
1897 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07001898 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001900 GrantedPermissions gp = (GrantedPermissions)obj;
1901 if (gp.grantedPermissions.contains(permName)) {
1902 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 }
1904 } else {
1905 HashSet<String> perms = mSystemPermissions.get(uid);
1906 if (perms != null && perms.contains(permName)) {
1907 return PackageManager.PERMISSION_GRANTED;
1908 }
1909 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07001910 if (!isPermissionEnforcedLocked(permName)) {
1911 return PackageManager.PERMISSION_GRANTED;
1912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 }
1914 return PackageManager.PERMISSION_DENIED;
1915 }
1916
1917 private BasePermission findPermissionTreeLP(String permName) {
1918 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1919 if (permName.startsWith(bp.name) &&
1920 permName.length() > bp.name.length() &&
1921 permName.charAt(bp.name.length()) == '.') {
1922 return bp;
1923 }
1924 }
1925 return null;
1926 }
1927
1928 private BasePermission checkPermissionTreeLP(String permName) {
1929 if (permName != null) {
1930 BasePermission bp = findPermissionTreeLP(permName);
1931 if (bp != null) {
Amith Yamasani742a6712011-05-04 14:49:28 -07001932 if (bp.uid == UserId.getAppId(Binder.getCallingUid())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 return bp;
1934 }
1935 throw new SecurityException("Calling uid "
1936 + Binder.getCallingUid()
1937 + " is not allowed to add to permission tree "
1938 + bp.name + " owned by uid " + bp.uid);
1939 }
1940 }
1941 throw new SecurityException("No permission tree found for " + permName);
1942 }
1943
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001944 static boolean compareStrings(CharSequence s1, CharSequence s2) {
1945 if (s1 == null) {
1946 return s2 == null;
1947 }
1948 if (s2 == null) {
1949 return false;
1950 }
1951 if (s1.getClass() != s2.getClass()) {
1952 return false;
1953 }
1954 return s1.equals(s2);
1955 }
1956
1957 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
1958 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07001959 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001960 if (pi1.protectionLevel != pi2.protectionLevel) return false;
1961 if (!compareStrings(pi1.name, pi2.name)) return false;
1962 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
1963 // We'll take care of setting this one.
1964 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
1965 // These are not currently stored in settings.
1966 //if (!compareStrings(pi1.group, pi2.group)) return false;
1967 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
1968 //if (pi1.labelRes != pi2.labelRes) return false;
1969 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
1970 return true;
1971 }
1972
1973 boolean addPermissionLocked(PermissionInfo info, boolean async) {
1974 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1975 throw new SecurityException("Label must be specified in permission");
1976 }
1977 BasePermission tree = checkPermissionTreeLP(info.name);
1978 BasePermission bp = mSettings.mPermissions.get(info.name);
1979 boolean added = bp == null;
1980 boolean changed = true;
Dianne Hackborne639da72012-02-21 15:11:13 -08001981 int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001982 if (added) {
1983 bp = new BasePermission(info.name, tree.sourcePackage,
1984 BasePermission.TYPE_DYNAMIC);
1985 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1986 throw new SecurityException(
1987 "Not allowed to modify non-dynamic permission "
1988 + info.name);
1989 } else {
Dianne Hackborne639da72012-02-21 15:11:13 -08001990 if (bp.protectionLevel == fixedLevel
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001991 && bp.perm.owner.equals(tree.perm.owner)
1992 && bp.uid == tree.uid
1993 && comparePermissionInfos(bp.perm.info, info)) {
1994 changed = false;
1995 }
1996 }
Dianne Hackborne639da72012-02-21 15:11:13 -08001997 bp.protectionLevel = fixedLevel;
1998 info = new PermissionInfo(info);
1999 info.protectionLevel = fixedLevel;
2000 bp.perm = new PackageParser.Permission(tree.perm.owner, info);
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002001 bp.perm.info.packageName = tree.perm.info.packageName;
2002 bp.uid = tree.uid;
2003 if (added) {
2004 mSettings.mPermissions.put(info.name, bp);
2005 }
2006 if (changed) {
2007 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07002008 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002009 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002010 scheduleWriteSettingsLocked();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002011 }
2012 }
2013 return added;
2014 }
2015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 public boolean addPermission(PermissionInfo info) {
2017 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07002018 return addPermissionLocked(info, false);
2019 }
2020 }
2021
2022 public boolean addPermissionAsync(PermissionInfo info) {
2023 synchronized (mPackages) {
2024 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 }
2026 }
2027
2028 public void removePermission(String name) {
2029 synchronized (mPackages) {
2030 checkPermissionTreeLP(name);
2031 BasePermission bp = mSettings.mPermissions.get(name);
2032 if (bp != null) {
2033 if (bp.type != BasePermission.TYPE_DYNAMIC) {
2034 throw new SecurityException(
2035 "Not allowed to modify non-dynamic permission "
2036 + name);
2037 }
2038 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07002039 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 }
2041 }
2042 }
2043
Dianne Hackborne639da72012-02-21 15:11:13 -08002044 public void grantPermission(String packageName, String permissionName) {
2045 mContext.enforceCallingOrSelfPermission(
2046 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2047 synchronized (mPackages) {
2048 final PackageParser.Package pkg = mPackages.get(packageName);
2049 if (pkg == null) {
2050 throw new IllegalArgumentException("Unknown package: " + packageName);
2051 }
2052 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2053 if (bp == null) {
2054 throw new IllegalArgumentException("Unknown permission: " + packageName);
2055 }
2056 if (!pkg.requestedPermissions.contains(permissionName)) {
2057 throw new SecurityException("Package " + packageName
2058 + " has not requested permission " + permissionName);
2059 }
2060 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2061 throw new SecurityException("Permission " + permissionName
2062 + " is not a development permission");
2063 }
2064 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2065 if (ps == null) {
2066 return;
2067 }
2068 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2069 if (gp.grantedPermissions.add(permissionName)) {
2070 if (ps.haveGids) {
2071 gp.gids = appendInts(gp.gids, bp.gids);
2072 }
2073 mSettings.writeLPr();
2074 }
2075 }
2076 }
2077
2078 public void revokePermission(String packageName, String permissionName) {
2079 synchronized (mPackages) {
2080 final PackageParser.Package pkg = mPackages.get(packageName);
2081 if (pkg == null) {
2082 throw new IllegalArgumentException("Unknown package: " + packageName);
2083 }
2084 if (pkg.applicationInfo.uid != Binder.getCallingUid()) {
2085 mContext.enforceCallingOrSelfPermission(
2086 android.Manifest.permission.GRANT_REVOKE_PERMISSIONS, null);
2087 }
2088 final BasePermission bp = mSettings.mPermissions.get(permissionName);
2089 if (bp == null) {
2090 throw new IllegalArgumentException("Unknown permission: " + packageName);
2091 }
2092 if (!pkg.requestedPermissions.contains(permissionName)) {
2093 throw new SecurityException("Package " + packageName
2094 + " has not requested permission " + permissionName);
2095 }
2096 if ((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) == 0) {
2097 throw new SecurityException("Permission " + permissionName
2098 + " is not a development permission");
2099 }
2100 final PackageSetting ps = (PackageSetting) pkg.mExtras;
2101 if (ps == null) {
2102 return;
2103 }
2104 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
2105 if (gp.grantedPermissions.remove(permissionName)) {
2106 gp.grantedPermissions.remove(permissionName);
2107 if (ps.haveGids) {
2108 gp.gids = removeInts(gp.gids, bp.gids);
2109 }
2110 mSettings.writeLPr();
2111 }
2112 }
2113 }
2114
Dianne Hackborn854060af2009-07-09 18:14:31 -07002115 public boolean isProtectedBroadcast(String actionName) {
2116 synchronized (mPackages) {
2117 return mProtectedBroadcasts.contains(actionName);
2118 }
2119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 public int checkSignatures(String pkg1, String pkg2) {
2122 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002123 final PackageParser.Package p1 = mPackages.get(pkg1);
2124 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 if (p1 == null || p1.mExtras == null
2126 || p2 == null || p2.mExtras == null) {
2127 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2128 }
Kenny Root447106f2011-03-23 11:00:15 -07002129 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 }
2131 }
2132
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002133 public int checkUidSignatures(int uid1, int uid2) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002134 // Map to base uids.
2135 uid1 = UserId.getAppId(uid1);
2136 uid2 = UserId.getAppId(uid2);
Kenny Root447106f2011-03-23 11:00:15 -07002137 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002138 synchronized (mPackages) {
2139 Signature[] s1;
2140 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07002141 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002142 if (obj != null) {
2143 if (obj instanceof SharedUserSetting) {
2144 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
2145 } else if (obj instanceof PackageSetting) {
2146 s1 = ((PackageSetting)obj).signatures.mSignatures;
2147 } else {
2148 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2149 }
2150 } else {
2151 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2152 }
Kenny Root447106f2011-03-23 11:00:15 -07002153 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002154 if (obj != null) {
2155 if (obj instanceof SharedUserSetting) {
2156 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
2157 } else if (obj instanceof PackageSetting) {
2158 s2 = ((PackageSetting)obj).signatures.mSignatures;
2159 } else {
2160 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2161 }
2162 } else {
2163 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
2164 }
Kenny Root447106f2011-03-23 11:00:15 -07002165 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002166 }
2167 }
2168
Kenny Root447106f2011-03-23 11:00:15 -07002169 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002170 if (s1 == null) {
2171 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 ? PackageManager.SIGNATURE_NEITHER_SIGNED
2173 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
2174 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07002175 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
2177 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002178 HashSet<Signature> set1 = new HashSet<Signature>();
2179 for (Signature sig : s1) {
2180 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002182 HashSet<Signature> set2 = new HashSet<Signature>();
2183 for (Signature sig : s2) {
2184 set2.add(sig);
2185 }
2186 // Make sure s2 contains all signatures in s1.
2187 if (set1.equals(set2)) {
2188 return PackageManager.SIGNATURE_MATCH;
2189 }
2190 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 }
2192
2193 public String[] getPackagesForUid(int uid) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002194 uid = UserId.getAppId(uid);
Kenny Root447106f2011-03-23 11:00:15 -07002195 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002197 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002199 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07002201 final String[] res = new String[N];
2202 final Iterator<PackageSetting> it = sus.packages.iterator();
2203 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 while (it.hasNext()) {
2205 res[i++] = it.next().name;
2206 }
2207 return res;
2208 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002209 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 return new String[] { ps.name };
2211 }
2212 }
2213 return null;
2214 }
2215
2216 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07002217 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 synchronized (mPackages) {
Amith Yamasani742a6712011-05-04 14:49:28 -07002219 Object obj = mSettings.getUserIdLPr(UserId.getAppId(uid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002221 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 return sus.name + ":" + sus.userId;
2223 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07002224 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 return ps.name;
2226 }
2227 }
2228 return null;
2229 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 public int getUidForSharedUser(String sharedUserName) {
2232 if(sharedUserName == null) {
2233 return -1;
2234 }
Kenny Root447106f2011-03-23 11:00:15 -07002235 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002237 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
Amith Yamasani742a6712011-05-04 14:49:28 -07002238 if (suid == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 return -1;
2240 }
2241 return suid.userId;
2242 }
2243 }
2244
Amith Yamasani483f3b02012-03-13 16:08:00 -07002245 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002247 int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002248 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002249 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
2250 return chooseBestActivity(intent, resolvedType, flags, query, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02002251 }
2252
Mihai Predaeae850c2009-05-13 10:13:48 +02002253 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002254 int flags, List<ResolveInfo> query, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002255 if (query != null) {
2256 final int N = query.size();
2257 if (N == 1) {
2258 return query.get(0);
2259 } else if (N > 1) {
2260 // If there is more than one activity with the same priority,
2261 // then let the user decide between them.
2262 ResolveInfo r0 = query.get(0);
2263 ResolveInfo r1 = query.get(1);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002264 if (DEBUG_INTENT_MATCHING) {
2265 Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
2266 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 }
2268 // If the first activity has a higher priority, or a different
2269 // default, then it is always desireable to pick it.
2270 if (r0.priority != r1.priority
2271 || r0.preferredOrder != r1.preferredOrder
2272 || r0.isDefault != r1.isDefault) {
2273 return query.get(0);
2274 }
2275 // If we have saved a preference for a preferred activity for
2276 // this Intent, use that.
2277 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002278 flags, query, r0.priority, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 if (ri != null) {
2280 return ri;
2281 }
2282 return mResolveInfo;
2283 }
2284 }
2285 return null;
2286 }
2287
2288 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002289 int flags, List<ResolveInfo> query, int priority, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002290 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002291 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 synchronized (mPackages) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002293 if (intent.getSelector() != null) {
2294 intent = intent.getSelector();
2295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2297 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002298 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002299 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002300 if (prefs != null && prefs.size() > 0) {
2301 // First figure out how good the original match set is.
2302 // We will only allow preferred activities that came
2303 // from the same match quality.
2304 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002305
2306 if (DEBUG_PREFERRED) {
2307 Log.v(TAG, "Figuring out best match...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 }
Kenny Root447106f2011-03-23 11:00:15 -07002309
2310 final int N = query.size();
2311 for (int j=0; j<N; j++) {
2312 final ResolveInfo ri = query.get(j);
2313 if (DEBUG_PREFERRED) {
2314 Log.v(TAG, "Match for " + ri.activityInfo + ": 0x"
2315 + Integer.toHexString(match));
2316 }
2317 if (ri.match > match) {
2318 match = ri.match;
2319 }
2320 }
2321
2322 if (DEBUG_PREFERRED) {
2323 Log.v(TAG, "Best match: 0x" + Integer.toHexString(match));
2324 }
2325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 match &= IntentFilter.MATCH_CATEGORY_MASK;
2327 final int M = prefs.size();
2328 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002329 final PreferredActivity pa = prefs.get(i);
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002330 if (pa.mPref.mMatch != match) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 continue;
2332 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07002333 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 if (DEBUG_PREFERRED) {
2335 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002336 if (ai != null) {
2337 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2338 } else {
2339 Log.v(TAG, " null");
2340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002342 if (ai == null) {
2343 // This previously registered preferred activity
2344 // component is no longer known. Most likely an update
2345 // to the app was installed and in the new version this
2346 // component no longer exists. Clean it up by removing
2347 // it from the preferred activities list, and skip it.
2348 Slog.w(TAG, "Removing dangling preferred activity: "
2349 + pa.mPref.mComponent);
2350 mSettings.mPreferredActivities.removeFilter(pa);
2351 continue;
2352 }
2353 for (int j=0; j<N; j++) {
2354 final ResolveInfo ri = query.get(j);
2355 if (!ri.activityInfo.applicationInfo.packageName
2356 .equals(ai.applicationInfo.packageName)) {
2357 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 }
Dianne Hackborn04505102012-02-29 12:34:04 -08002359 if (!ri.activityInfo.name.equals(ai.name)) {
2360 continue;
2361 }
2362
2363 // Okay we found a previously set preferred app.
2364 // If the result set is different from when this
2365 // was created, we need to clear it and re-ask the
2366 // user their preference.
2367 if (!pa.mPref.sameSet(query, priority)) {
2368 Slog.i(TAG, "Result set changed, dropping preferred activity for "
2369 + intent + " type " + resolvedType);
2370 mSettings.mPreferredActivities.removeFilter(pa);
2371 return null;
2372 }
2373
2374 // Yay!
2375 return ri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 }
2377 }
2378 }
2379 }
2380 return null;
2381 }
2382
Amith Yamasani483f3b02012-03-13 16:08:00 -07002383 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 public List<ResolveInfo> queryIntentActivities(Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002385 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002386 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002387 ComponentName comp = intent.getComponent();
2388 if (comp == null) {
2389 if (intent.getSelector() != null) {
2390 intent = intent.getSelector();
2391 comp = intent.getComponent();
2392 }
2393 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002396 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002397 final ActivityInfo ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002399 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 ri.activityInfo = ai;
2401 list.add(ri);
2402 }
2403 return list;
2404 }
2405
Kenny Root447106f2011-03-23 11:00:15 -07002406 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002408 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002409 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002410 return mActivities.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002411 }
Kenny Root447106f2011-03-23 11:00:15 -07002412 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002413 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002414 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002415 pkg.activities, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002416 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002417 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 }
2419 }
2420
Amith Yamasani483f3b02012-03-13 16:08:00 -07002421 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2423 Intent[] specifics, String[] specificTypes, Intent intent,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002424 String resolvedType, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002425 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 final String resultsAction = intent.getAction();
2427
Kenny Root447106f2011-03-23 11:00:15 -07002428 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
Amith Yamasani483f3b02012-03-13 16:08:00 -07002429 | PackageManager.GET_RESOLVED_FILTER, userId);
Kenny Root447106f2011-03-23 11:00:15 -07002430
2431 if (DEBUG_INTENT_MATCHING) {
2432 Log.v(TAG, "Query " + intent + ": " + results);
2433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434
2435 int specificsPos = 0;
2436 int N;
2437
2438 // todo: note that the algorithm used here is O(N^2). This
2439 // isn't a problem in our current environment, but if we start running
2440 // into situations where we have more than 5 or 10 matches then this
2441 // should probably be changed to something smarter...
2442
2443 // First we go through and resolve each of the specific items
2444 // that were supplied, taking care of removing any corresponding
2445 // duplicate items in the generic resolve list.
2446 if (specifics != null) {
2447 for (int i=0; i<specifics.length; i++) {
2448 final Intent sintent = specifics[i];
2449 if (sintent == null) {
2450 continue;
2451 }
2452
Kenny Root447106f2011-03-23 11:00:15 -07002453 if (DEBUG_INTENT_MATCHING) {
2454 Log.v(TAG, "Specific #" + i + ": " + sintent);
2455 }
2456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 String action = sintent.getAction();
2458 if (resultsAction != null && resultsAction.equals(action)) {
2459 // If this action was explicitly requested, then don't
2460 // remove things that have it.
2461 action = null;
2462 }
Kenny Root447106f2011-03-23 11:00:15 -07002463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 ResolveInfo ri = null;
2465 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002466
2467 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 if (comp == null) {
2469 ri = resolveIntent(
2470 sintent,
2471 specificTypes != null ? specificTypes[i] : null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002472 flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 if (ri == null) {
2474 continue;
2475 }
2476 if (ri == mResolveInfo) {
2477 // ACK! Must do something better with this.
2478 }
2479 ai = ri.activityInfo;
2480 comp = new ComponentName(ai.applicationInfo.packageName,
2481 ai.name);
2482 } else {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002483 ai = getActivityInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 if (ai == null) {
2485 continue;
2486 }
2487 }
2488
2489 // Look for any generic query activities that are duplicates
2490 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002491 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 N = results.size();
2493 int j;
2494 for (j=specificsPos; j<N; j++) {
2495 ResolveInfo sri = results.get(j);
2496 if ((sri.activityInfo.name.equals(comp.getClassName())
2497 && sri.activityInfo.applicationInfo.packageName.equals(
2498 comp.getPackageName()))
2499 || (action != null && sri.filter.matchAction(action))) {
2500 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002501 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 TAG, "Removing duplicate item from " + j
2503 + " due to specific " + specificsPos);
2504 if (ri == null) {
2505 ri = sri;
2506 }
2507 j--;
2508 N--;
2509 }
2510 }
2511
2512 // Add this specific item to its proper place.
2513 if (ri == null) {
2514 ri = new ResolveInfo();
2515 ri.activityInfo = ai;
2516 }
2517 results.add(specificsPos, ri);
2518 ri.specificIndex = i;
2519 specificsPos++;
2520 }
2521 }
2522
2523 // Now we go through the remaining generic results and remove any
2524 // duplicate actions that are found here.
2525 N = results.size();
2526 for (int i=specificsPos; i<N-1; i++) {
2527 final ResolveInfo rii = results.get(i);
2528 if (rii.filter == null) {
2529 continue;
2530 }
2531
2532 // Iterate over all of the actions of this result's intent
2533 // filter... typically this should be just one.
2534 final Iterator<String> it = rii.filter.actionsIterator();
2535 if (it == null) {
2536 continue;
2537 }
2538 while (it.hasNext()) {
2539 final String action = it.next();
2540 if (resultsAction != null && resultsAction.equals(action)) {
2541 // If this action was explicitly requested, then don't
2542 // remove things that have it.
2543 continue;
2544 }
2545 for (int j=i+1; j<N; j++) {
2546 final ResolveInfo rij = results.get(j);
2547 if (rij.filter != null && rij.filter.hasAction(action)) {
2548 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002549 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 TAG, "Removing duplicate item from " + j
2551 + " due to action " + action + " at " + i);
2552 j--;
2553 N--;
2554 }
2555 }
2556 }
2557
2558 // If the caller didn't request filter information, drop it now
2559 // so we don't have to marshall/unmarshall it.
2560 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2561 rii.filter = null;
2562 }
2563 }
2564
2565 // Filter out the caller activity if so requested.
2566 if (caller != null) {
2567 N = results.size();
2568 for (int i=0; i<N; i++) {
2569 ActivityInfo ainfo = results.get(i).activityInfo;
2570 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2571 && caller.getClassName().equals(ainfo.name)) {
2572 results.remove(i);
2573 break;
2574 }
2575 }
2576 }
2577
2578 // If the caller didn't request filter information,
2579 // drop them now so we don't have to
2580 // marshall/unmarshall it.
2581 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2582 N = results.size();
2583 for (int i=0; i<N; i++) {
2584 results.get(i).filter = null;
2585 }
2586 }
2587
Kenny Root9718cf52011-02-23 16:45:26 -08002588 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 return results;
2590 }
2591
Amith Yamasani483f3b02012-03-13 16:08:00 -07002592 @Override
2593 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
2594 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002595 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002596 ComponentName comp = intent.getComponent();
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002597 if (comp == null) {
2598 if (intent.getSelector() != null) {
2599 intent = intent.getSelector();
2600 comp = intent.getComponent();
2601 }
2602 }
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002603 if (comp != null) {
2604 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002605 ActivityInfo ai = getReceiverInfo(comp, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002606 if (ai != null) {
2607 ResolveInfo ri = new ResolveInfo();
2608 ri.activityInfo = ai;
2609 list.add(ri);
2610 }
2611 return list;
2612 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002613
Kenny Root447106f2011-03-23 11:00:15 -07002614 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002616 String pkgName = intent.getPackage();
2617 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002618 return mReceivers.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002619 }
Kenny Root447106f2011-03-23 11:00:15 -07002620 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002621 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002622 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
2623 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002624 }
2625 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 }
2627 }
2628
Amith Yamasani483f3b02012-03-13 16:08:00 -07002629 @Override
2630 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
2631 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07002632 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 if (query != null) {
2634 if (query.size() >= 1) {
2635 // If there is more than one service with the same priority,
2636 // just arbitrarily pick the first one.
2637 return query.get(0);
2638 }
2639 }
2640 return null;
2641 }
2642
Amith Yamasani483f3b02012-03-13 16:08:00 -07002643 @Override
2644 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
2645 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002646 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -08002647 ComponentName comp = intent.getComponent();
2648 if (comp == null) {
2649 if (intent.getSelector() != null) {
2650 intent = intent.getSelector();
2651 comp = intent.getComponent();
2652 }
2653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002655 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
Amith Yamasani483f3b02012-03-13 16:08:00 -07002656 final ServiceInfo si = getServiceInfo(comp, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002658 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 ri.serviceInfo = si;
2660 list.add(ri);
2661 }
2662 return list;
2663 }
2664
Kenny Root447106f2011-03-23 11:00:15 -07002665 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002666 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002667 String pkgName = intent.getPackage();
2668 if (pkgName == null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002669 return mServices.queryIntent(intent, resolvedType, flags, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002670 }
Kenny Root447106f2011-03-23 11:00:15 -07002671 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002672 if (pkg != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002673 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
2674 userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002675 }
2676 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002677 }
2678 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002679
Kenny Root0e2c0f32011-04-15 17:50:10 -07002680 private static final int getContinuationPoint(final String[] keys, final String key) {
2681 final int index;
2682 if (key == null) {
2683 index = 0;
2684 } else {
2685 final int insertPoint = Arrays.binarySearch(keys, key);
2686 if (insertPoint < 0) {
2687 index = -insertPoint;
2688 } else {
2689 index = insertPoint + 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 }
2691 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002692 return index;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 }
2694
Kenny Root0e2c0f32011-04-15 17:50:10 -07002695 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
2696 final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
2697 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2698 final String[] keys;
Amith Yamasani483f3b02012-03-13 16:08:00 -07002699 int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700
Kenny Root447106f2011-03-23 11:00:15 -07002701 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 synchronized (mPackages) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002703 if (listUninstalled) {
2704 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2705 } else {
2706 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2707 }
2708
2709 Arrays.sort(keys);
2710 int i = getContinuationPoint(keys, lastRead);
2711 final int N = keys.length;
2712
2713 while (i < N) {
2714 final String packageName = keys[i++];
2715
2716 PackageInfo pi = null;
2717 if (listUninstalled) {
2718 final PackageSetting ps = mSettings.mPackages.get(packageName);
2719 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002720 pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002722 } else {
2723 final PackageParser.Package p = mPackages.get(packageName);
2724 if (p != null) {
Amith Yamasani13593602012-03-22 16:16:17 -07002725 pi = generatePackageInfo(p, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 }
2727 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002728
Henrik Engström9771a312012-02-21 09:05:17 +01002729 if (pi != null && list.append(pi)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002730 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
2732 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002733
2734 if (i == N) {
2735 list.setLastSlice(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002738
2739 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 }
2741
Amith Yamasani483f3b02012-03-13 16:08:00 -07002742 @Override
Kenny Root0e2c0f32011-04-15 17:50:10 -07002743 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
Amith Yamasani483f3b02012-03-13 16:08:00 -07002744 String lastRead, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002745 if (!sUserManager.exists(userId)) return null;
Kenny Root0e2c0f32011-04-15 17:50:10 -07002746 final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
2747 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
2748 final String[] keys;
2749
Kenny Root447106f2011-03-23 11:00:15 -07002750 // writer
Kenny Root0e2c0f32011-04-15 17:50:10 -07002751 synchronized (mPackages) {
2752 if (listUninstalled) {
2753 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
2754 } else {
2755 keys = mPackages.keySet().toArray(new String[mPackages.size()]);
2756 }
2757
2758 Arrays.sort(keys);
2759 int i = getContinuationPoint(keys, lastRead);
2760 final int N = keys.length;
2761
2762 while (i < N) {
2763 final String packageName = keys[i++];
2764
2765 ApplicationInfo ai = null;
Amith Yamasani13593602012-03-22 16:16:17 -07002766 final PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002767 if (listUninstalled) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002768 if (ps != null) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07002769 ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId);
Kenny Root0e2c0f32011-04-15 17:50:10 -07002770 }
2771 } else {
2772 final PackageParser.Package p = mPackages.get(packageName);
Amith Yamasani13593602012-03-22 16:16:17 -07002773 if (p != null && ps != null) {
2774 ai = PackageParser.generateApplicationInfo(p, flags, ps.getStopped(userId),
2775 ps.getEnabled(userId), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 }
2777 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002778
Henrik Engström9771a312012-02-21 09:05:17 +01002779 if (ai != null && list.append(ai)) {
Kenny Root0e2c0f32011-04-15 17:50:10 -07002780 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 }
2782 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002783
2784 if (i == N) {
2785 list.setLastSlice(true);
2786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002787 }
Kenny Root0e2c0f32011-04-15 17:50:10 -07002788
2789 return list;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 }
2791
2792 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002793 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794
Kenny Root447106f2011-03-23 11:00:15 -07002795 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002796 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002797 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002798 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002800 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 if (p.applicationInfo != null
2802 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002803 && (!mSafeMode || isSystemApp(p))) {
Amith Yamasani13593602012-03-22 16:16:17 -07002804 PackageSetting ps = mSettings.mPackages.get(p.packageName);
2805 finalList.add(PackageParser.generateApplicationInfo(p, flags,
2806 ps != null ? ps.getStopped(userId) : false,
2807 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2808 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809 }
2810 }
2811 }
2812
2813 return finalList;
2814 }
2815
Amith Yamasani483f3b02012-03-13 16:08:00 -07002816 @Override
2817 public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07002818 if (!sUserManager.exists(userId)) return null;
Kenny Root447106f2011-03-23 11:00:15 -07002819 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 synchronized (mPackages) {
2821 final PackageParser.Provider provider = mProviders.get(name);
Amith Yamasani13593602012-03-22 16:16:17 -07002822 PackageSetting ps = provider != null
2823 ? mSettings.mPackages.get(provider.owner.packageName)
2824 : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825 return provider != null
Amith Yamasani483f3b02012-03-13 16:08:00 -07002826 && mSettings.isEnabledLPr(provider.info, flags, userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 && (!mSafeMode || (provider.info.applicationInfo.flags
2828 &ApplicationInfo.FLAG_SYSTEM) != 0)
Amith Yamasani13593602012-03-22 16:16:17 -07002829 ? PackageParser.generateProviderInfo(provider, flags,
2830 ps != null ? ps.getStopped(userId) : false,
2831 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2832 userId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 : null;
2834 }
2835 }
2836
Fred Quintana718d8a22009-04-29 17:53:20 -07002837 /**
2838 * @deprecated
2839 */
Kenny Root60f7ad82011-03-22 12:49:06 -07002840 @Deprecated
2841 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07002842 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002843 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002844 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
2845 .iterator();
Amith Yamasani13593602012-03-22 16:16:17 -07002846 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002847 while (i.hasNext()) {
2848 Map.Entry<String, PackageParser.Provider> entry = i.next();
2849 PackageParser.Provider p = entry.getValue();
Amith Yamasani13593602012-03-22 16:16:17 -07002850 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851
2852 if (p.syncable
2853 && (!mSafeMode || (p.info.applicationInfo.flags
2854 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2855 outNames.add(entry.getKey());
Amith Yamasani13593602012-03-22 16:16:17 -07002856 outInfo.add(PackageParser.generateProviderInfo(p, 0,
2857 ps != null ? ps.getStopped(userId) : false,
2858 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2859 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 }
2861 }
2862 }
2863 }
2864
2865 public List<ProviderInfo> queryContentProviders(String processName,
2866 int uid, int flags) {
2867 ArrayList<ProviderInfo> finalList = null;
2868
Kenny Root447106f2011-03-23 11:00:15 -07002869 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002871 final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
Amith Yamasani483f3b02012-03-13 16:08:00 -07002872 final int userId = processName != null ?
2873 UserId.getUserId(uid) : UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002875 final PackageParser.Provider p = i.next();
Amith Yamasani13593602012-03-22 16:16:17 -07002876 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 if (p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07002878 && (processName == null
2879 || (p.info.processName.equals(processName)
Amith Yamasani483f3b02012-03-13 16:08:00 -07002880 && UserId.isSameApp(p.info.applicationInfo.uid, uid)))
2881 && mSettings.isEnabledLPr(p.info, flags, userId)
Kenny Root447106f2011-03-23 11:00:15 -07002882 && (!mSafeMode
2883 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 if (finalList == null) {
2885 finalList = new ArrayList<ProviderInfo>(3);
2886 }
Amith Yamasani13593602012-03-22 16:16:17 -07002887 finalList.add(PackageParser.generateProviderInfo(p, flags,
2888 ps != null ? ps.getStopped(userId) : false,
2889 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
2890 userId));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 }
2892 }
2893 }
2894
2895 if (finalList != null) {
2896 Collections.sort(finalList, mProviderInitOrderSorter);
2897 }
2898
2899 return finalList;
2900 }
2901
2902 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2903 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002904 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 synchronized (mPackages) {
2906 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2907 return PackageParser.generateInstrumentationInfo(i, flags);
2908 }
2909 }
2910
2911 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2912 int flags) {
2913 ArrayList<InstrumentationInfo> finalList =
2914 new ArrayList<InstrumentationInfo>();
2915
Kenny Root447106f2011-03-23 11:00:15 -07002916 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002917 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002918 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002920 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 if (targetPackage == null
2922 || targetPackage.equals(p.info.targetPackage)) {
2923 finalList.add(PackageParser.generateInstrumentationInfo(p,
2924 flags));
2925 }
2926 }
2927 }
2928
2929 return finalList;
2930 }
2931
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002932 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07002934 if (files == null) {
2935 Log.d(TAG, "No files in app dir " + dir);
2936 return;
2937 }
2938
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002939 if (DEBUG_PACKAGE_SCANNING) {
Joe Onorato431bb222010-10-18 19:13:23 -04002940 Log.d(TAG, "Scanning app dir " + dir);
2941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942
2943 int i;
2944 for (i=0; i<files.length; i++) {
2945 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002946 if (!isPackageFilename(files[i])) {
2947 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002948 continue;
2949 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002950 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002951 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002952 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002953 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2954 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002955 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002956 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002957 file.delete();
2958 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 }
2960 }
2961
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002962 private static File getSettingsProblemFile() {
2963 File dataDir = Environment.getDataDirectory();
2964 File systemDir = new File(dataDir, "system");
2965 File fname = new File(systemDir, "uiderrors.txt");
2966 return fname;
2967 }
2968
Kenny Rootcf0b38c2011-03-22 14:17:59 -07002969 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002971 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 FileOutputStream out = new FileOutputStream(fname, true);
2973 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002974 SimpleDateFormat formatter = new SimpleDateFormat();
2975 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2976 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 pw.close();
2978 FileUtils.setPermissions(
2979 fname.toString(),
2980 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2981 -1, -1);
2982 } catch (java.io.IOException e) {
2983 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002984 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
2986
2987 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2988 PackageParser.Package pkg, File srcFile, int parseFlags) {
2989 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07002990 if (ps != null
2991 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07002992 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07002993 if (ps.signatures.mSignatures != null
2994 && ps.signatures.mSignatures.length != 0) {
2995 // Optimization: reuse the existing cached certificates
2996 // if the package appears to be unchanged.
2997 pkg.mSignatures = ps.signatures.mSignatures;
2998 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 }
Jeff Browne7600722010-04-07 18:28:23 -07003000
3001 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003002 } else {
Jeff Browne7600722010-04-07 18:28:23 -07003003 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
3004 }
3005
3006 if (!pp.collectCertificates(pkg, parseFlags)) {
3007 mLastScanError = pp.getParseError();
3008 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 }
3010 }
3011 return true;
3012 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 /*
3015 * Scan a package and return the newly parsed package.
3016 * Returns null in case of errors and the error code is stored in mLastScanError
3017 */
3018 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003019 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003020 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003021 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003022 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003023 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 pp.setSeparateProcesses(mSeparateProcesses);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07003025 pp.setOnlyCoreApps(mOnlyCore);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003027 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 if (pkg == null) {
3029 mLastScanError = pp.getParseError();
3030 return null;
3031 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003032 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07003034 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003035 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003036 // Look to see if we already know about this package.
3037 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003038 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003039 // This package has been renamed to its original name. Let's
3040 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07003041 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003042 }
3043 // If there was no original package, see one for the real package name.
3044 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07003045 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003046 }
3047 // Check to see if this package could be hiding/updating a system
3048 // package. Must look for it either under the original or real
3049 // package name depending on our state.
3050 updatedPkg = mSettings.mDisabledSysPackages.get(
3051 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003052 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003053 // First check if this is a system package that may involve an update
3054 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07003055 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003056 // The path has changed from what was last scanned... check the
3057 // version of the new path against what we have stored to determine
3058 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003059 if (pkg.mVersionCode < ps.versionCode) {
3060 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003061 // Ignore entry. Skip it.
3062 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07003063 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003064 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003065 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3066 return null;
3067 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003068 // The current app on the system partion is better than
3069 // what we have updated to on the data partition; switch
3070 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003071 // At this point, its safely assumed that package installation for
3072 // apps in system partition will go through. If not there won't be a working
3073 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07003074 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003075 synchronized (mPackages) {
3076 // Just remove the loaded entries from package lists.
3077 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003078 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003079 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003080 + "reverting from " + ps.codePathString
3081 + ": new version " + pkg.mVersionCode
3082 + " better than installed " + ps.versionCode);
Kenny Root85387d72010-08-26 10:13:11 -07003083 InstallArgs args = new FileInstallArgs(ps.codePathString,
3084 ps.resourcePathString, ps.nativeLibraryPathString);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003085 args.cleanUpResourcesLI();
Kenny Root447106f2011-03-23 11:00:15 -07003086 mSettings.enableSystemPackageLPw(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003088 }
3089 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003090 if (updatedPkg != null) {
3091 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
3092 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
3093 }
3094 // Verify certificates against what was last scanned
3095 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003096 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003097 return null;
3098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 // The apk is forward locked (not public) if its code and resources
3100 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003101 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003103 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07003104 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003105
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003106 String codePath = null;
3107 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003108 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
3109 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003110 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003111 } else {
3112 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003113 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003114 }
3115 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003116 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003117 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003118 codePath = pkg.mScanPath;
3119 // Set application objects path explicitly.
3120 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 // Note that we invoke the following method only if we are about to unpack an application
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003122 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003123 }
3124
Kenny Root85387d72010-08-26 10:13:11 -07003125 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
3126 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08003127 pkg.mPath = pkg.mScanPath = destCodePath;
3128 pkg.applicationInfo.sourceDir = destCodePath;
3129 pkg.applicationInfo.publicSourceDir = destResPath;
3130 }
3131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 private static String fixProcessName(String defProcessName,
3133 String processName, int uid) {
3134 if (processName == null) {
3135 return defProcessName;
3136 }
3137 return processName;
3138 }
3139
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003140 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003141 PackageParser.Package pkg) {
3142 if (pkgSetting.signatures.mSignatures != null) {
3143 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07003144 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003145 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003146 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003147 + " signatures do not match the previously installed version; ignoring!");
3148 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 return false;
3150 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003151 }
3152 // Check for shared user signatures
3153 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003154 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003155 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3156 Slog.e(TAG, "Package " + pkg.packageName
3157 + " has no signatures that match those in shared user "
3158 + pkgSetting.sharedUser.name + "; ignoring!");
3159 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
3160 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 }
3163 return true;
3164 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003165
Kenny Root461ff1f2011-08-09 09:43:03 -07003166 /**
3167 * Enforces that only the system UID or root's UID can call a method exposed
3168 * via Binder.
3169 *
3170 * @param message used as message if SecurityException is thrown
3171 * @throws SecurityException if the caller is not system or root
3172 */
3173 private static final void enforceSystemOrRoot(String message) {
3174 final int uid = Binder.getCallingUid();
3175 if (uid != Process.SYSTEM_UID && uid != 0) {
3176 throw new SecurityException(message);
3177 }
3178 }
3179
Dianne Hackborn661cd522011-08-22 00:26:20 -07003180 public void performBootDexOpt() {
3181 ArrayList<PackageParser.Package> pkgs = null;
3182 synchronized (mPackages) {
3183 if (mDeferredDexOpt.size() > 0) {
3184 pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt);
3185 mDeferredDexOpt.clear();
3186 }
3187 }
3188 if (pkgs != null) {
3189 for (int i=0; i<pkgs.size(); i++) {
Dianne Hackborn58f42a52011-10-10 13:46:34 -07003190 if (!isFirstBoot()) {
3191 try {
3192 ActivityManagerNative.getDefault().showBootMessage(
3193 mContext.getResources().getString(
3194 com.android.internal.R.string.android_upgrading_apk,
3195 i+1, pkgs.size()), true);
3196 } catch (RemoteException e) {
3197 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003198 }
3199 PackageParser.Package p = pkgs.get(i);
3200 synchronized (mInstallLock) {
3201 if (!p.mDidDexOpt) {
3202 performDexOptLI(p, false, false);
3203 }
3204 }
3205 }
3206 }
3207 }
3208
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003209 public boolean performDexOpt(String packageName) {
Kenny Root461ff1f2011-08-09 09:43:03 -07003210 enforceSystemOrRoot("Only the system can request dexopt be performed");
3211
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003212 if (!mNoDexOpt) {
3213 return false;
3214 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003215
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003216 PackageParser.Package p;
3217 synchronized (mPackages) {
3218 p = mPackages.get(packageName);
3219 if (p == null || p.mDidDexOpt) {
3220 return false;
3221 }
3222 }
3223 synchronized (mInstallLock) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003224 return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003225 }
3226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003227
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003228 static final int DEX_OPT_SKIPPED = 0;
3229 static final int DEX_OPT_PERFORMED = 1;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003230 static final int DEX_OPT_DEFERRED = 2;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003231 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003232
Dianne Hackborn661cd522011-08-22 00:26:20 -07003233 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003234 boolean performed = false;
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003235 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003236 String path = pkg.mScanPath;
3237 int ret = 0;
3238 try {
3239 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003240 if (!forceDex && defer) {
3241 mDeferredDexOpt.add(pkg);
3242 return DEX_OPT_DEFERRED;
3243 } else {
3244 Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
3245 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
3246 !isForwardLocked(pkg));
3247 pkg.mDidDexOpt = true;
3248 performed = true;
3249 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003250 }
3251 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003252 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003253 ret = -1;
3254 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07003255 Slog.w(TAG, "IOException reading apk: " + path, e);
3256 ret = -1;
3257 } catch (dalvik.system.StaleDexCacheError e) {
3258 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
3259 ret = -1;
3260 } catch (Exception e) {
3261 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003262 ret = -1;
3263 }
3264 if (ret < 0) {
3265 //error from installer
3266 return DEX_OPT_FAILED;
3267 }
3268 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003269
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003270 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
3271 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08003272
Kenny Root447106f2011-03-23 11:00:15 -07003273 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003274 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003275 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003276 + " to " + newPkg.packageName
3277 + ": old package not in system partition");
3278 return false;
3279 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003280 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003281 + " to " + newPkg.packageName
3282 + ": old package still exists");
3283 return false;
3284 }
3285 return true;
3286 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003287
Amith Yamasani0b285492011-04-14 17:35:23 -07003288 File getDataPathForUser(int userId) {
3289 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003290 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003291
3292 private File getDataPathForPackage(String packageName, int userId) {
Kenny Root9c8625e2011-07-25 09:42:22 -07003293 /*
3294 * Until we fully support multiple users, return the directory we
3295 * previously would have. The PackageManagerTests will need to be
3296 * revised when this is changed back..
3297 */
3298 if (userId == 0) {
3299 return new File(mAppDataDir, packageName);
3300 } else {
3301 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003302 + File.separator + packageName);
Kenny Root9c8625e2011-07-25 09:42:22 -07003303 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003304 }
3305
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003306 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003307 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003308 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08003309 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
3310 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003311 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003312 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08003313 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
3314 return null;
3315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 mScanningPath = scanFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3319 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
3320 }
3321
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003322 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 synchronized (mPackages) {
3324 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003325 Slog.w(TAG, "*************************************************");
3326 Slog.w(TAG, "Core android package being redefined. Skipping.");
3327 Slog.w(TAG, " file=" + mScanningPath);
3328 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3330 return null;
3331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333 // Set up information for our fall-back user intent resolution
3334 // activity.
3335 mPlatformPackage = pkg;
3336 pkg.mVersionCode = mSdkVersion;
3337 mAndroidApplication = pkg.applicationInfo;
3338 mResolveActivity.applicationInfo = mAndroidApplication;
3339 mResolveActivity.name = ResolverActivity.class.getName();
3340 mResolveActivity.packageName = mAndroidApplication.packageName;
3341 mResolveActivity.processName = mAndroidApplication.processName;
3342 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
3343 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08003344 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003345 mResolveActivity.exported = true;
3346 mResolveActivity.enabled = true;
3347 mResolveInfo.activityInfo = mResolveActivity;
3348 mResolveInfo.priority = 0;
3349 mResolveInfo.preferredOrder = 0;
3350 mResolveInfo.match = 0;
3351 mResolveComponentName = new ComponentName(
3352 mAndroidApplication.packageName, mResolveActivity.name);
3353 }
3354 }
3355
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003356 if (DEBUG_PACKAGE_SCANNING) {
3357 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3358 Log.d(TAG, "Scanning package " + pkg.packageName);
3359 }
3360
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003361 if (mPackages.containsKey(pkg.packageName)
3362 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003363 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
3366 return null;
3367 }
3368
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003369 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003370 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
3371 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 SharedUserSetting suid = null;
3374 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003375
Kenny Root502e9a42011-01-10 13:48:15 -08003376 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003377 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08003378 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003379 pkg.mRealPackage = null;
3380 pkg.mAdoptPermissions = null;
3381 }
Kenny Root502e9a42011-01-10 13:48:15 -08003382
Kenny Root447106f2011-03-23 11:00:15 -07003383 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 synchronized (mPackages) {
3385 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07003386 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
3387 if (mTmpSharedLibraries == null ||
3388 mTmpSharedLibraries.length < mSharedLibraries.size()) {
3389 mTmpSharedLibraries = new String[mSharedLibraries.size()];
3390 }
3391 int num = 0;
3392 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
3393 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003394 final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003396 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07003398 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003399 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
3400 return null;
3401 }
Dianne Hackborn49237342009-08-27 20:08:01 -07003402 mTmpSharedLibraries[num] = file;
3403 num++;
3404 }
3405 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
3406 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003407 final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
Dianne Hackborn49237342009-08-27 20:08:01 -07003408 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003409 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07003410 + " desires unavailable shared library "
3411 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
3412 } else {
3413 mTmpSharedLibraries[num] = file;
3414 num++;
3415 }
3416 }
3417 if (num > 0) {
3418 pkg.usesLibraryFiles = new String[num];
3419 System.arraycopy(mTmpSharedLibraries, 0,
3420 pkg.usesLibraryFiles, 0, num);
3421 }
Kenny Root1683afa2011-01-07 14:27:50 -08003422 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 if (pkg.mSharedUserId != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003425 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 pkg.applicationInfo.flags, true);
3427 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003428 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 + " for shared user failed");
3430 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3431 return null;
3432 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003433 if (DEBUG_PACKAGE_SCANNING) {
3434 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3435 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
3436 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 }
3438 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003439
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003440 // Check if we are renaming from an original package name.
3441 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003442 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08003443 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003444 // This package may need to be renamed to a previously
3445 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07003446 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003447 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003448 // This package had originally been installed as the
3449 // original name, and we have already taken care of
3450 // transitioning to the new one. Just update the new
3451 // one to continue using the old name.
3452 realName = pkg.mRealPackage;
3453 if (!pkg.packageName.equals(renamed)) {
3454 // Callers into this function may have already taken
3455 // care of renaming the package; only do it here if
3456 // it is not already done.
3457 pkg.setPackageName(renamed);
3458 }
3459
Dianne Hackbornc1552392010-03-03 16:19:01 -08003460 } else {
3461 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07003462 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08003463 pkg.mOriginalPackages.get(i))) != null) {
3464 // We do have the package already installed under its
3465 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07003466 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08003467 // New package is not compatible with original.
3468 origPackage = null;
3469 continue;
3470 } else if (origPackage.sharedUser != null) {
3471 // Make sure uid is compatible between packages.
3472 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003473 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003474 + " to " + pkg.packageName + ": old uid "
3475 + origPackage.sharedUser.name
3476 + " differs from " + pkg.mSharedUserId);
3477 origPackage = null;
3478 continue;
3479 }
3480 } else {
3481 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3482 + pkg.packageName + " to old name " + origPackage.name);
3483 }
3484 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003485 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003486 }
3487 }
3488 }
3489
3490 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003491 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003492 + " was transferred to another, but its .apk remains");
3493 }
3494
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003495 // Just create the setting, don't add it yet. For already existing packages
3496 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07003497 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003498 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3499 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003501 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3503 return null;
3504 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003505
3506 if (pkgSetting.origPackage != null) {
3507 // If we are first transitioning from an original package,
3508 // fix up the new package's name now. We need to do this after
3509 // looking up the package under its new name, so getPackageLP
3510 // can take care of fiddling things correctly.
3511 pkg.setPackageName(origPackage.name);
3512
3513 // File a report about this.
3514 String msg = "New package " + pkgSetting.realName
3515 + " renamed to replace old package " + pkgSetting.name;
3516 reportSettingsProblem(Log.WARN, msg);
3517
3518 // Make a note of it.
3519 mTransferedPackages.add(origPackage.name);
3520
3521 // No longer need to retain this.
3522 pkgSetting.origPackage = null;
3523 }
3524
3525 if (realName != null) {
3526 // Make a note of it.
3527 mTransferedPackages.add(pkg.packageName);
3528 }
3529
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003530 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3532 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003533
Amith Yamasani13593602012-03-22 16:16:17 -07003534 pkg.applicationInfo.uid = pkgSetting.appId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003536
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003537 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003538 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 return null;
3540 }
3541 // The signature has changed, but this package is in the system
3542 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003543 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 // However... if this package is part of a shared user, but it
3545 // doesn't match the signature of the shared user, let's fail.
3546 // What this means is that you can't change the signatures
3547 // associated with an overall shared user, which doesn't seem all
3548 // that unreasonable.
3549 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003550 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003551 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3552 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003553 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3554 return null;
3555 }
3556 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003557 // File a report about this.
3558 String msg = "System package " + pkg.packageName
3559 + " signature changed; retaining data.";
3560 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003561 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003562
The Android Open Source Project10592532009-03-18 17:39:46 -07003563 // Verify that this new package doesn't have any content providers
3564 // that conflict with existing packages. Only do this if the
3565 // package isn't already installed, since we don't want to break
3566 // things that are installed.
3567 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08003568 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07003569 int i;
3570 for (i=0; i<N; i++) {
3571 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003572 if (p.info.authority != null) {
3573 String names[] = p.info.authority.split(";");
3574 for (int j = 0; j < names.length; j++) {
3575 if (mProviders.containsKey(names[j])) {
3576 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003577 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003578 " (in package " + pkg.applicationInfo.packageName +
3579 ") is already used by "
3580 + ((other != null && other.getComponentName() != null)
3581 ? other.getComponentName().getPackageName() : "?"));
3582 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3583 return null;
3584 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003585 }
3586 }
3587 }
3588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589
Kenny Root447106f2011-03-23 11:00:15 -07003590 if (pkg.mAdoptPermissions != null) {
3591 // This package wants to adopt ownership of permissions from
3592 // another package.
3593 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
3594 final String origName = pkg.mAdoptPermissions.get(i);
3595 final PackageSetting orig = mSettings.peekPackageLPr(origName);
3596 if (orig != null) {
3597 if (verifyPackageUpdateLPr(orig, pkg)) {
3598 Slog.i(TAG, "Adopting permissions from " + origName + " to "
3599 + pkg.packageName);
3600 mSettings.transferPermissionsLPw(origName, pkg.packageName);
3601 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003602 }
3603 }
3604 }
3605 }
Kenny Root447106f2011-03-23 11:00:15 -07003606
3607 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003608
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003609 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 pkg.applicationInfo.processName = fixProcessName(
3612 pkg.applicationInfo.packageName,
3613 pkg.applicationInfo.processName,
3614 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615
3616 File dataPath;
3617 if (mPlatformPackage == pkg) {
3618 // The system package is special.
3619 dataPath = new File (Environment.getDataDirectory(), "system");
3620 pkg.applicationInfo.dataDir = dataPath.getPath();
3621 } else {
3622 // This is a normal package, need to make its data directory.
Amith Yamasani0b285492011-04-14 17:35:23 -07003623 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003624
3625 boolean uidError = false;
3626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 if (dataPath.exists()) {
3628 mOutPermissions[1] = 0;
3629 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003630
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003631 // If we have mismatched owners for the data path, we have a problem.
Jeff Brown10e89712011-07-08 18:52:57 -07003632 if (mOutPermissions[1] != pkg.applicationInfo.uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 boolean recovered = false;
3634 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3635 // If this is a system app, we can at least delete its
3636 // current data so the application will still work.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003637 int ret = mInstaller.remove(pkgName, 0);
3638 if (ret >= 0) {
3639 // TODO: Kill the processes first
3640 // Remove the data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003641 sUserManager.removePackageForAllUsers(pkgName);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003642 // Old data gone!
3643 String msg = "System package " + pkg.packageName
3644 + " has changed from uid: "
3645 + mOutPermissions[1] + " to "
3646 + pkg.applicationInfo.uid + "; old data erased";
3647 reportSettingsProblem(Log.WARN, msg);
3648 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003649
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003650 // And now re-install the app.
3651 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3652 pkg.applicationInfo.uid);
3653 if (ret == -1) {
3654 // Ack should not happen!
3655 msg = "System package " + pkg.packageName
3656 + " could not have data directory re-created after delete.";
3657 reportSettingsProblem(Log.WARN, msg);
3658 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3659 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003661 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003662 sUserManager.installPackageForAllUsers(pkgName,
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003663 pkg.applicationInfo.uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003665 if (!recovered) {
3666 mHasSystemUidErrors = true;
3667 }
3668 }
3669 if (!recovered) {
3670 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3671 + pkg.applicationInfo.uid + "/fs_"
3672 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003673 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 String msg = "Package " + pkg.packageName
3675 + " has mismatched uid: "
3676 + mOutPermissions[1] + " on disk, "
3677 + pkg.applicationInfo.uid + " in settings";
Kenny Root447106f2011-03-23 11:00:15 -07003678 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003680 mSettings.mReadMessages.append(msg);
3681 mSettings.mReadMessages.append('\n');
3682 uidError = true;
3683 if (!pkgSetting.uidError) {
3684 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 }
3687 }
3688 }
3689 pkg.applicationInfo.dataDir = dataPath.getPath();
3690 } else {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003691 if (DEBUG_PACKAGE_SCANNING) {
3692 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3693 Log.v(TAG, "Want this data dir: " + dataPath);
3694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 //invoke installer to do the actual installation
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003696 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
3697 pkg.applicationInfo.uid);
3698 if (ret < 0) {
3699 // Error from installer
3700 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3701 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003703 // Create data directories for all users
Amith Yamasani13593602012-03-22 16:16:17 -07003704 sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003706 if (dataPath.exists()) {
3707 pkg.applicationInfo.dataDir = dataPath.getPath();
3708 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003709 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 pkg.applicationInfo.dataDir = null;
3711 }
3712 }
Kenny Root85387d72010-08-26 10:13:11 -07003713
3714 /*
3715 * Set the data dir to the default "/data/data/<package name>/lib"
3716 * if we got here without anyone telling us different (e.g., apps
3717 * stored on SD card have their native libraries stored in the ASEC
3718 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003719 *
3720 * This happens during an upgrade from a package settings file that
3721 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003722 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003723 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3724 if (pkgSetting.nativeLibraryPathString == null) {
3725 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3726 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3727 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3728 } else {
3729 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3730 }
Kenny Root85387d72010-08-26 10:13:11 -07003731 }
3732
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003733 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003734 }
3735
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003736 String path = scanFile.getPath();
3737 /* Note: We don't want to unpack the native binaries for
3738 * system applications, unless they have been updated
3739 * (the binaries are already under /system/lib).
3740 * Also, don't unpack libs for apps on the external card
3741 * since they should have their libraries in the ASEC
3742 * container already.
3743 *
3744 * In other words, we're going to unpack the binaries
3745 * only for non-system apps and system app upgrades.
3746 */
3747 if (pkg.applicationInfo.nativeLibraryDir != null) {
3748 try {
3749 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
Kenny Root5832ead2011-08-02 15:47:08 -07003750 final String dataPathString = dataPath.getCanonicalPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07003751
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003752 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3753 /*
3754 * Upgrading from a previous version of the OS sometimes
3755 * leaves native libraries in the /data/data/<app>/lib
3756 * directory for system apps even when they shouldn't be.
3757 * Recent changes in the JNI library search path
3758 * necessitates we remove those to match previous behavior.
3759 */
3760 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
3761 Log.i(TAG, "removed obsolete native libraries for system package "
3762 + path);
Kenny Root831baa22010-10-05 12:29:25 -07003763 }
Kenny Root5832ead2011-08-02 15:47:08 -07003764 } else if (nativeLibraryDir.getParentFile().getCanonicalPath()
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003765 .equals(dataPathString)) {
3766 /*
Kenny Root66269ea2011-07-12 14:14:01 -07003767 * Make sure the native library dir isn't a symlink to
3768 * something. If it is, ask installd to remove it and create
3769 * a directory so we can copy to it afterwards.
3770 */
3771 boolean isSymLink;
3772 try {
3773 isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
3774 } catch (ErrnoException e) {
3775 // This shouldn't happen, but we'll fail-safe.
3776 isSymLink = true;
3777 }
3778 if (isSymLink) {
3779 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3780 }
3781
3782 /*
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003783 * If this is an internal application or our
3784 * nativeLibraryPath points to our data directory, unpack
Kenny Root66269ea2011-07-12 14:14:01 -07003785 * the libraries if necessary.
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003786 */
Kenny Root66269ea2011-07-12 14:14:01 -07003787 NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003788 } else {
3789 Slog.i(TAG, "Linking native library dir for " + path);
3790 mInstaller.linkNativeLibraryDirectory(dataPathString,
3791 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003792 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003793 } catch (IOException ioe) {
3794 Log.e(TAG, "Unable to get canonical file " + ioe.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003796 }
3797 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003798
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003799 if ((scanMode&SCAN_NO_DEX) == 0) {
Dianne Hackborn661cd522011-08-22 00:26:20 -07003800 if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0)
3801 == DEX_OPT_FAILED) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07003802 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3803 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 if (mFactoryTest && pkg.requestedPermissions.contains(
3808 android.Manifest.permission.FACTORY_TEST)) {
3809 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3810 }
3811
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003812 // Request the ActivityManager to kill the process(only for existing packages)
3813 // so that we do not end up in a confused state while the user is still using the older
3814 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003815 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003816 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003817 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003818 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003819
Kenny Root447106f2011-03-23 11:00:15 -07003820 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003822 // We don't expect installation to fail beyond this point,
3823 if ((scanMode&SCAN_MONITOR) != 0) {
3824 mAppDirs.put(pkg.mPath, pkg);
3825 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07003827 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003829 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003830 // Make sure we don't accidentally delete its data.
3831 mSettings.mPackagesToBeCleaned.remove(pkgName);
3832
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003833 // Take care of first install / last update times.
3834 if (currentTime != 0) {
3835 if (pkgSetting.firstInstallTime == 0) {
3836 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
3837 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
3838 pkgSetting.lastUpdateTime = currentTime;
3839 }
3840 } else if (pkgSetting.firstInstallTime == 0) {
3841 // We need *something*. Take time time stamp of the file.
3842 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
3843 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
3844 if (scanFileTime != pkgSetting.timeStamp) {
3845 // A package on the system image has changed; consider this
3846 // to be an update.
3847 pkgSetting.lastUpdateTime = scanFileTime;
3848 }
3849 }
3850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003851 int N = pkg.providers.size();
3852 StringBuilder r = null;
3853 int i;
3854 for (i=0; i<N; i++) {
3855 PackageParser.Provider p = pkg.providers.get(i);
3856 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3857 p.info.processName, pkg.applicationInfo.uid);
3858 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3859 p.info.name), p);
3860 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003861 if (p.info.authority != null) {
3862 String names[] = p.info.authority.split(";");
3863 p.info.authority = null;
3864 for (int j = 0; j < names.length; j++) {
3865 if (j == 1 && p.syncable) {
3866 // We only want the first authority for a provider to possibly be
3867 // syncable, so if we already added this provider using a different
3868 // authority clear the syncable flag. We copy the provider before
3869 // changing it because the mProviders object contains a reference
3870 // to a provider that we don't want to change.
3871 // Only do this for the second authority since the resulting provider
3872 // object can be the same for all future authorities for this provider.
3873 p = new PackageParser.Provider(p);
3874 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003876 if (!mProviders.containsKey(names[j])) {
3877 mProviders.put(names[j], p);
3878 if (p.info.authority == null) {
3879 p.info.authority = names[j];
3880 } else {
3881 p.info.authority = p.info.authority + ";" + names[j];
3882 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003883 if (DEBUG_PACKAGE_SCANNING) {
3884 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3885 Log.d(TAG, "Registered content provider: " + names[j]
3886 + ", className = " + p.info.name + ", isSyncable = "
3887 + p.info.isSyncable);
3888 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003889 } else {
3890 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003891 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003892 " (in package " + pkg.applicationInfo.packageName +
3893 "): name already used by "
3894 + ((other != null && other.getComponentName() != null)
3895 ? other.getComponentName().getPackageName() : "?"));
3896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 }
3898 }
3899 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3900 if (r == null) {
3901 r = new StringBuilder(256);
3902 } else {
3903 r.append(' ');
3904 }
3905 r.append(p.info.name);
3906 }
3907 }
3908 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003909 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 N = pkg.services.size();
3913 r = null;
3914 for (i=0; i<N; i++) {
3915 PackageParser.Service s = pkg.services.get(i);
3916 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3917 s.info.processName, pkg.applicationInfo.uid);
3918 mServices.addService(s);
3919 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3920 if (r == null) {
3921 r = new StringBuilder(256);
3922 } else {
3923 r.append(' ');
3924 }
3925 r.append(s.info.name);
3926 }
3927 }
3928 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003929 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 N = pkg.receivers.size();
3933 r = null;
3934 for (i=0; i<N; i++) {
3935 PackageParser.Activity a = pkg.receivers.get(i);
3936 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3937 a.info.processName, pkg.applicationInfo.uid);
3938 mReceivers.addActivity(a, "receiver");
3939 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3940 if (r == null) {
3941 r = new StringBuilder(256);
3942 } else {
3943 r.append(' ');
3944 }
3945 r.append(a.info.name);
3946 }
3947 }
3948 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003949 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 N = pkg.activities.size();
3953 r = null;
3954 for (i=0; i<N; i++) {
3955 PackageParser.Activity a = pkg.activities.get(i);
3956 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3957 a.info.processName, pkg.applicationInfo.uid);
3958 mActivities.addActivity(a, "activity");
3959 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3960 if (r == null) {
3961 r = new StringBuilder(256);
3962 } else {
3963 r.append(' ');
3964 }
3965 r.append(a.info.name);
3966 }
3967 }
3968 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003969 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 N = pkg.permissionGroups.size();
3973 r = null;
3974 for (i=0; i<N; i++) {
3975 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3976 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3977 if (cur == null) {
3978 mPermissionGroups.put(pg.info.name, pg);
3979 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3980 if (r == null) {
3981 r = new StringBuilder(256);
3982 } else {
3983 r.append(' ');
3984 }
3985 r.append(pg.info.name);
3986 }
3987 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003988 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 + pg.info.packageName + " ignored: original from "
3990 + cur.info.packageName);
3991 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3992 if (r == null) {
3993 r = new StringBuilder(256);
3994 } else {
3995 r.append(' ');
3996 }
3997 r.append("DUP:");
3998 r.append(pg.info.name);
3999 }
4000 }
4001 }
4002 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004003 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 N = pkg.permissions.size();
4007 r = null;
4008 for (i=0; i<N; i++) {
4009 PackageParser.Permission p = pkg.permissions.get(i);
4010 HashMap<String, BasePermission> permissionMap =
4011 p.tree ? mSettings.mPermissionTrees
4012 : mSettings.mPermissions;
4013 p.group = mPermissionGroups.get(p.info.group);
4014 if (p.info.group == null || p.group != null) {
4015 BasePermission bp = permissionMap.get(p.info.name);
4016 if (bp == null) {
4017 bp = new BasePermission(p.info.name, p.info.packageName,
4018 BasePermission.TYPE_NORMAL);
4019 permissionMap.put(p.info.name, bp);
4020 }
4021 if (bp.perm == null) {
4022 if (bp.sourcePackage == null
4023 || bp.sourcePackage.equals(p.info.packageName)) {
4024 BasePermission tree = findPermissionTreeLP(p.info.name);
4025 if (tree == null
4026 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004027 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 bp.perm = p;
4029 bp.uid = pkg.applicationInfo.uid;
4030 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4031 if (r == null) {
4032 r = new StringBuilder(256);
4033 } else {
4034 r.append(' ');
4035 }
4036 r.append(p.info.name);
4037 }
4038 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004039 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 + p.info.packageName + " ignored: base tree "
4041 + tree.name + " is from package "
4042 + tree.sourcePackage);
4043 }
4044 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004045 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004046 + p.info.packageName + " ignored: original from "
4047 + bp.sourcePackage);
4048 }
4049 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4050 if (r == null) {
4051 r = new StringBuilder(256);
4052 } else {
4053 r.append(' ');
4054 }
4055 r.append("DUP:");
4056 r.append(p.info.name);
4057 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004058 if (bp.perm == p) {
4059 bp.protectionLevel = p.info.protectionLevel;
4060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004062 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 + p.info.packageName + " ignored: no group "
4064 + p.group);
4065 }
4066 }
4067 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004068 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004069 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004071 N = pkg.instrumentation.size();
4072 r = null;
4073 for (i=0; i<N; i++) {
4074 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
4075 a.info.packageName = pkg.applicationInfo.packageName;
4076 a.info.sourceDir = pkg.applicationInfo.sourceDir;
4077 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
4078 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07004079 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004080 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
4082 if (r == null) {
4083 r = new StringBuilder(256);
4084 } else {
4085 r.append(' ');
4086 }
4087 r.append(a.info.name);
4088 }
4089 }
4090 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004091 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004093
Dianne Hackborn854060af2009-07-09 18:14:31 -07004094 if (pkg.protectedBroadcasts != null) {
4095 N = pkg.protectedBroadcasts.size();
4096 for (i=0; i<N; i++) {
4097 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
4098 }
4099 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 pkgSetting.setTimeStamp(scanFileTime);
4102 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 return pkg;
4105 }
4106
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004107 private void killApplication(String pkgName, int uid) {
4108 // Request the ActivityManager to kill the process(only for existing packages)
4109 // so that we do not end up in a confused state while the user is still using the older
4110 // version of the application while the new one gets installed.
4111 IActivityManager am = ActivityManagerNative.getDefault();
4112 if (am != null) {
4113 try {
4114 am.killApplicationWithUid(pkgName, uid);
4115 } catch (RemoteException e) {
4116 }
4117 }
4118 }
4119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004121 if (DEBUG_INSTALL) {
4122 if (chatty)
4123 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
4124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125
Kenny Root447106f2011-03-23 11:00:15 -07004126 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 mPackages.remove(pkg.applicationInfo.packageName);
4129 if (pkg.mPath != null) {
4130 mAppDirs.remove(pkg.mPath);
4131 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 int N = pkg.providers.size();
4134 StringBuilder r = null;
4135 int i;
4136 for (i=0; i<N; i++) {
4137 PackageParser.Provider p = pkg.providers.get(i);
4138 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
4139 p.info.name));
4140 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 /* The is another ContentProvider with this authority when
4143 * this app was installed so this authority is null,
4144 * Ignore it as we don't have to unregister the provider.
4145 */
4146 continue;
4147 }
4148 String names[] = p.info.authority.split(";");
4149 for (int j = 0; j < names.length; j++) {
4150 if (mProviders.get(names[j]) == p) {
4151 mProviders.remove(names[j]);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004152 if (DEBUG_REMOVE) {
4153 if (chatty)
4154 Log.d(TAG, "Unregistered content provider: " + names[j]
4155 + ", className = " + p.info.name + ", isSyncable = "
4156 + p.info.isSyncable);
4157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159 }
4160 if (chatty) {
4161 if (r == null) {
4162 r = new StringBuilder(256);
4163 } else {
4164 r.append(' ');
4165 }
4166 r.append(p.info.name);
4167 }
4168 }
4169 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004170 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 N = pkg.services.size();
4174 r = null;
4175 for (i=0; i<N; i++) {
4176 PackageParser.Service s = pkg.services.get(i);
4177 mServices.removeService(s);
4178 if (chatty) {
4179 if (r == null) {
4180 r = new StringBuilder(256);
4181 } else {
4182 r.append(' ');
4183 }
4184 r.append(s.info.name);
4185 }
4186 }
4187 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004188 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 N = pkg.receivers.size();
4192 r = null;
4193 for (i=0; i<N; i++) {
4194 PackageParser.Activity a = pkg.receivers.get(i);
4195 mReceivers.removeActivity(a, "receiver");
4196 if (chatty) {
4197 if (r == null) {
4198 r = new StringBuilder(256);
4199 } else {
4200 r.append(' ');
4201 }
4202 r.append(a.info.name);
4203 }
4204 }
4205 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004206 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004207 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004209 N = pkg.activities.size();
4210 r = null;
4211 for (i=0; i<N; i++) {
4212 PackageParser.Activity a = pkg.activities.get(i);
4213 mActivities.removeActivity(a, "activity");
4214 if (chatty) {
4215 if (r == null) {
4216 r = new StringBuilder(256);
4217 } else {
4218 r.append(' ');
4219 }
4220 r.append(a.info.name);
4221 }
4222 }
4223 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004224 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 N = pkg.permissions.size();
4228 r = null;
4229 for (i=0; i<N; i++) {
4230 PackageParser.Permission p = pkg.permissions.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 BasePermission bp = mSettings.mPermissions.get(p.info.name);
4232 if (bp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 bp = mSettings.mPermissionTrees.get(p.info.name);
4234 }
4235 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004236 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 if (chatty) {
4238 if (r == null) {
4239 r = new StringBuilder(256);
4240 } else {
4241 r.append(' ');
4242 }
4243 r.append(p.info.name);
4244 }
4245 }
4246 }
4247 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004248 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 N = pkg.instrumentation.size();
4252 r = null;
4253 for (i=0; i<N; i++) {
4254 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004255 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 if (chatty) {
4257 if (r == null) {
4258 r = new StringBuilder(256);
4259 } else {
4260 r.append(' ');
4261 }
4262 r.append(a.info.name);
4263 }
4264 }
4265 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08004266 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 }
4268 }
4269 }
4270
4271 private static final boolean isPackageFilename(String name) {
4272 return name != null && name.endsWith(".apk");
4273 }
4274
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004275 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
4276 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
4277 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
4278 return true;
4279 }
4280 }
4281 return false;
4282 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004283
4284 static final int UPDATE_PERMISSIONS_ALL = 1<<0;
4285 static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1;
4286 static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2;
4287
Kenny Root447106f2011-03-23 11:00:15 -07004288 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborne639da72012-02-21 15:11:13 -08004289 PackageParser.Package pkgInfo, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07004291 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004293 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004294 if (bp.packageSetting == null) {
4295 // We may not yet have parsed the package, so just see if
4296 // we still know about its settings.
4297 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4298 }
4299 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004300 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 + " from package " + bp.sourcePackage);
4302 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004303 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4304 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4305 Slog.i(TAG, "Removing old permission tree: " + bp.name
4306 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004307 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004308 it.remove();
4309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 }
4311 }
4312
4313 // Make sure all dynamic permissions have been assigned to a package,
4314 // and make sure there are no dangling permissions.
4315 it = mSettings.mPermissions.values().iterator();
4316 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07004317 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 if (bp.type == BasePermission.TYPE_DYNAMIC) {
4319 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
4320 + bp.name + " pkg=" + bp.sourcePackage
4321 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004322 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004323 final BasePermission tree = findPermissionTreeLP(bp.name);
Dianne Hackbornd2509fd2011-09-12 12:29:43 -07004324 if (tree != null && tree.perm != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004325 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 bp.perm = new PackageParser.Permission(tree.perm.owner,
4327 new PermissionInfo(bp.pendingInfo));
4328 bp.perm.info.packageName = tree.perm.info.packageName;
4329 bp.perm.info.name = bp.name;
4330 bp.uid = tree.uid;
4331 }
4332 }
4333 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004334 if (bp.packageSetting == null) {
4335 // We may not yet have parsed the package, so just see if
4336 // we still know about its settings.
4337 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
4338 }
4339 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004340 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 + " from package " + bp.sourcePackage);
4342 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004343 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
4344 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
4345 Slog.i(TAG, "Removing old permission: " + bp.name
4346 + " from package " + bp.sourcePackage);
Dianne Hackborne639da72012-02-21 15:11:13 -08004347 flags |= UPDATE_PERMISSIONS_ALL;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004348 it.remove();
4349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350 }
4351 }
4352
4353 // Now update the permissions for all packages, in particular
4354 // replace the granted permissions of the system packages.
Dianne Hackborne639da72012-02-21 15:11:13 -08004355 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004356 for (PackageParser.Package pkg : mPackages.values()) {
4357 if (pkg != pkgInfo) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004358 grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004359 }
4360 }
4361 }
4362
4363 if (pkgInfo != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004364 grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 }
4366 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004367
Kenny Root447106f2011-03-23 11:00:15 -07004368 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
4369 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 if (ps == null) {
4371 return;
4372 }
4373 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborne639da72012-02-21 15:11:13 -08004374 HashSet<String> origPermissions = gp.grantedPermissions;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004375 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377 if (replace) {
4378 ps.permissionsFixed = false;
4379 if (gp == ps) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004380 origPermissions = new HashSet<String>(gp.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 gp.grantedPermissions.clear();
4382 gp.gids = mGlobalGids;
4383 }
4384 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 if (gp.gids == null) {
4387 gp.gids = mGlobalGids;
4388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 final int N = pkg.requestedPermissions.size();
4391 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07004392 final String name = pkg.requestedPermissions.get(i);
Dianne Hackborne639da72012-02-21 15:11:13 -08004393 //final boolean required = pkg.requestedPermssionsRequired.get(i);
Kenny Root447106f2011-03-23 11:00:15 -07004394 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004395 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004396 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004397 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 }
4399 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004400 if (bp != null && bp.packageSetting != null) {
4401 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004403 boolean allowedSig = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004404 final int level = bp.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
4405 if (level == PermissionInfo.PROTECTION_NORMAL
4406 || level == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07004408 } else if (bp.packageSetting == null) {
4409 // This permission is invalid; skip it.
4410 allowed = false;
Dianne Hackborne639da72012-02-21 15:11:13 -08004411 } else if (level == PermissionInfo.PROTECTION_SIGNATURE) {
Kenny Root447106f2011-03-23 11:00:15 -07004412 allowed = (compareSignatures(
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004413 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 == PackageManager.SIGNATURE_MATCH)
Kenny Root447106f2011-03-23 11:00:15 -07004415 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborne639da72012-02-21 15:11:13 -08004417 if (!allowed && (bp.protectionLevel
4418 & PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
Kenny Root85387d72010-08-26 10:13:11 -07004419 if (isSystemApp(pkg)) {
Dianne Hackborne639da72012-02-21 15:11:13 -08004420 // For updated system applications, a system permission
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07004422 if (isUpdatedSystemApp(pkg)) {
Kenny Root447106f2011-03-23 11:00:15 -07004423 final PackageSetting sysPs = mSettings
4424 .getDisabledSystemPkgLPr(pkg.packageName);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07004425 final GrantedPermissions origGp = sysPs.sharedUser != null
4426 ? sysPs.sharedUser : sysPs;
4427 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 allowed = true;
4429 } else {
4430 allowed = false;
4431 }
4432 } else {
4433 allowed = true;
4434 }
4435 }
4436 }
Dianne Hackborne639da72012-02-21 15:11:13 -08004437 if (!allowed && (bp.protectionLevel
4438 & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) {
4439 // For development permissions, a development permission
4440 // is granted only if it was already granted.
4441 if (origPermissions.contains(perm)) {
4442 allowed = true;
4443 } else {
4444 allowed = false;
4445 }
4446 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004447 if (allowed) {
4448 allowedSig = true;
4449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 } else {
4451 allowed = false;
4452 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004453 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004454 if (gp != ps) {
4455 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4456 }
4457 }
4458 if (allowed) {
4459 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4460 && ps.permissionsFixed) {
4461 // If this is an existing, non-system package, then
4462 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004463 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004465 // Except... if this is a permission that was added
4466 // to the platform (note: need to only do this when
4467 // updating the platform).
4468 final int NP = PackageParser.NEW_PERMISSIONS.length;
4469 for (int ip=0; ip<NP; ip++) {
4470 final PackageParser.NewPermissionInfo npi
4471 = PackageParser.NEW_PERMISSIONS[ip];
4472 if (npi.name.equals(perm)
4473 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4474 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004475 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004476 + pkg.packageName);
4477 break;
4478 }
4479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481 }
4482 if (allowed) {
4483 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004484 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 gp.grantedPermissions.add(perm);
4486 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004487 } else if (!ps.haveGids) {
4488 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 }
4490 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004491 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 + " to package " + pkg.packageName
4493 + " because it was previously installed without");
4494 }
4495 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004496 if (gp.grantedPermissions.remove(perm)) {
4497 changedPermission = true;
4498 gp.gids = removeInts(gp.gids, bp.gids);
4499 Slog.i(TAG, "Un-granting permission " + perm
4500 + " from package " + pkg.packageName
4501 + " (protectionLevel=" + bp.protectionLevel
4502 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4503 + ")");
4504 } else {
4505 Slog.w(TAG, "Not granting permission " + perm
4506 + " to package " + pkg.packageName
4507 + " (protectionLevel=" + bp.protectionLevel
4508 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4509 + ")");
4510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 }
4512 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004513 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 + " in package " + pkg.packageName);
4515 }
4516 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004517
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004518 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004519 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4520 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 // This is the first that we have heard about this package, so the
4522 // permissions we have now selected are fixed until explicitly
4523 // changed.
4524 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004525 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004526 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004529 private final class ActivityIntentResolver
4530 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004531 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004532 boolean defaultOnly, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004533 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004535 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
4537
Amith Yamasani483f3b02012-03-13 16:08:00 -07004538 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4539 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004540 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004541 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004542 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004543 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 }
4545
Kenny Root60f7ad82011-03-22 12:49:06 -07004546 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004547 int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004548 if (!sUserManager.exists(userId)) return null;
Mihai Predaeae850c2009-05-13 10:13:48 +02004549 if (packageActivities == null) {
4550 return null;
4551 }
4552 mFlags = flags;
4553 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004554 final int N = packageActivities.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004555 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4556 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004557
4558 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004559 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004560 intentFilters = packageActivities.get(i).intents;
4561 if (intentFilters != null && intentFilters.size() > 0) {
4562 listCut.add(intentFilters);
4563 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004564 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004565 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Mihai Predaeae850c2009-05-13 10:13:48 +02004566 }
4567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004569 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004570 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08004571 if (DEBUG_SHOW_INFO)
4572 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004573 TAG, " " + type + " " +
4574 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004575 if (DEBUG_SHOW_INFO)
4576 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08004577 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004578 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004580 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4581 intent.setPriority(0);
4582 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4583 + a.className + " with priority > 0, forcing to 0");
4584 }
Kenny Root9718cf52011-02-23 16:45:26 -08004585 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 Log.v(TAG, " IntentFilter:");
4587 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4588 }
4589 if (!intent.debugCheck()) {
4590 Log.w(TAG, "==> For Activity " + a.info.name);
4591 }
4592 addFilter(intent);
4593 }
4594 }
4595
4596 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004597 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004598 if (DEBUG_SHOW_INFO) {
4599 Log.v(TAG, " " + type + " "
4600 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
4601 : a.info.name) + ":");
4602 Log.v(TAG, " Class=" + a.info.name);
4603 }
4604 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004605 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004607 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 Log.v(TAG, " IntentFilter:");
4609 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4610 }
4611 removeFilter(intent);
4612 }
4613 }
4614
4615 @Override
4616 protected boolean allowFilterResult(
4617 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4618 ActivityInfo filterAi = filter.activity.info;
4619 for (int i=dest.size()-1; i>=0; i--) {
4620 ActivityInfo destAi = dest.get(i).activityInfo;
4621 if (destAi.name == filterAi.name
4622 && destAi.packageName == filterAi.packageName) {
4623 return false;
4624 }
4625 }
4626 return true;
4627 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07004630 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004631 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004632 PackageParser.Package p = filter.activity.owner;
4633 if (p != null) {
4634 PackageSetting ps = (PackageSetting)p.mExtras;
4635 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004636 // System apps are never considered stopped for purposes of
4637 // filtering, because there may be no way for the user to
4638 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07004639 return ps.getStopped(userId) && (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004640 }
4641 }
4642 return false;
4643 }
4644
4645 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004646 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4647 return info.activity.owner.packageName;
4648 }
4649
4650 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004651 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004652 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004653 if (!sUserManager.exists(userId)) return null;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004654 if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 return null;
4656 }
4657 final PackageParser.Activity activity = info.activity;
4658 if (mSafeMode && (activity.info.applicationInfo.flags
4659 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4660 return null;
4661 }
4662 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07004663 PackageSetting ps = (PackageSetting) activity.owner.mExtras;
4664 res.activityInfo = PackageParser.generateActivityInfo(activity, mFlags,
4665 ps != null ? ps.getStopped(userId) : false,
4666 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
4667 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004668 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4669 res.filter = info;
4670 }
4671 res.priority = info.getPriority();
4672 res.preferredOrder = activity.owner.mPreferredOrder;
4673 //System.out.println("Result: " + res.activityInfo.className +
4674 // " = " + res.priority);
4675 res.match = match;
4676 res.isDefault = info.hasDefault;
4677 res.labelRes = info.labelRes;
4678 res.nonLocalizedLabel = info.nonLocalizedLabel;
4679 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07004680 res.system = isSystemApp(res.activityInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 return res;
4682 }
4683
4684 @Override
4685 protected void sortResults(List<ResolveInfo> results) {
4686 Collections.sort(results, mResolvePrioritySorter);
4687 }
4688
4689 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004690 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004692 out.print(prefix); out.print(
4693 Integer.toHexString(System.identityHashCode(filter.activity)));
4694 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004695 out.print(filter.activity.getComponentShortName());
4696 out.print(" filter ");
4697 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004698 }
4699
4700// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4701// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4702// final List<ResolveInfo> retList = Lists.newArrayList();
4703// while (i.hasNext()) {
4704// final ResolveInfo resolveInfo = i.next();
4705// if (isEnabledLP(resolveInfo.activityInfo)) {
4706// retList.add(resolveInfo);
4707// }
4708// }
4709// return retList;
4710// }
4711
4712 // Keys are String (activity class name), values are Activity.
4713 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4714 = new HashMap<ComponentName, PackageParser.Activity>();
4715 private int mFlags;
4716 }
4717
4718 private final class ServiceIntentResolver
4719 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004720 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004721 boolean defaultOnly, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004723 return super.queryIntent(intent, resolvedType, defaultOnly, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 }
4725
Amith Yamasani483f3b02012-03-13 16:08:00 -07004726 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
4727 int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004728 if (!sUserManager.exists(userId)) return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004729 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004730 return super.queryIntent(intent, resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004731 (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 }
4733
Kenny Root60f7ad82011-03-22 12:49:06 -07004734 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004735 int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004736 if (!sUserManager.exists(userId)) return null;
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004737 if (packageServices == null) {
4738 return null;
4739 }
4740 mFlags = flags;
4741 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004742 final int N = packageServices.size();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004743 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4744 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4745
4746 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4747 for (int i = 0; i < N; ++i) {
4748 intentFilters = packageServices.get(i).intents;
4749 if (intentFilters != null && intentFilters.size() > 0) {
4750 listCut.add(intentFilters);
4751 }
4752 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07004753 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004754 }
4755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004757 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08004758 if (DEBUG_SHOW_INFO) {
4759 Log.v(TAG, " "
4760 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004762 Log.v(TAG, " Class=" + s.info.name);
4763 }
4764 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 int j;
4766 for (j=0; j<NI; j++) {
4767 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004768 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 Log.v(TAG, " IntentFilter:");
4770 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4771 }
4772 if (!intent.debugCheck()) {
4773 Log.w(TAG, "==> For Service " + s.info.name);
4774 }
4775 addFilter(intent);
4776 }
4777 }
4778
4779 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004780 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004781 if (DEBUG_SHOW_INFO) {
4782 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004783 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004784 Log.v(TAG, " Class=" + s.info.name);
4785 }
4786 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004787 int j;
4788 for (j=0; j<NI; j++) {
4789 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004790 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 Log.v(TAG, " IntentFilter:");
4792 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4793 }
4794 removeFilter(intent);
4795 }
4796 }
4797
4798 @Override
4799 protected boolean allowFilterResult(
4800 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4801 ServiceInfo filterSi = filter.service.info;
4802 for (int i=dest.size()-1; i>=0; i--) {
4803 ServiceInfo destAi = dest.get(i).serviceInfo;
4804 if (destAi.name == filterSi.name
4805 && destAi.packageName == filterSi.packageName) {
4806 return false;
4807 }
4808 }
4809 return true;
4810 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004812 @Override
Amith Yamasani483f3b02012-03-13 16:08:00 -07004813 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004814 if (!sUserManager.exists(userId)) return true;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004815 PackageParser.Package p = filter.service.owner;
4816 if (p != null) {
4817 PackageSetting ps = (PackageSetting)p.mExtras;
4818 if (ps != null) {
Dianne Hackborn80a7ac12011-09-22 18:32:52 -07004819 // System apps are never considered stopped for purposes of
4820 // filtering, because there may be no way for the user to
4821 // actually re-launch them.
Amith Yamasani483f3b02012-03-13 16:08:00 -07004822 return ps.getStopped(userId)
4823 && (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0;
Dianne Hackborne7f97212011-02-24 14:40:20 -08004824 }
4825 }
4826 return false;
4827 }
4828
4829 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004830 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
4831 return info.service.owner.packageName;
4832 }
4833
4834 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
Amith Yamasani483f3b02012-03-13 16:08:00 -07004836 int match, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07004837 if (!sUserManager.exists(userId)) return null;
Jason parksa3cdaa52011-01-13 14:15:43 -06004838 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Amith Yamasani483f3b02012-03-13 16:08:00 -07004839 if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 return null;
4841 }
4842 final PackageParser.Service service = info.service;
4843 if (mSafeMode && (service.info.applicationInfo.flags
4844 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4845 return null;
4846 }
4847 final ResolveInfo res = new ResolveInfo();
Amith Yamasani13593602012-03-22 16:16:17 -07004848 PackageSetting ps = (PackageSetting) service.owner.mExtras;
4849 res.serviceInfo = PackageParser.generateServiceInfo(service, mFlags,
4850 ps != null ? ps.getStopped(userId) : false,
4851 ps != null ? ps.getEnabled(userId) : COMPONENT_ENABLED_STATE_DEFAULT,
4852 userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4854 res.filter = filter;
4855 }
4856 res.priority = info.getPriority();
4857 res.preferredOrder = service.owner.mPreferredOrder;
4858 //System.out.println("Result: " + res.activityInfo.className +
4859 // " = " + res.priority);
4860 res.match = match;
4861 res.isDefault = info.hasDefault;
4862 res.labelRes = info.labelRes;
4863 res.nonLocalizedLabel = info.nonLocalizedLabel;
4864 res.icon = info.icon;
Dianne Hackbornd99b2932011-08-18 14:39:58 -07004865 res.system = isSystemApp(res.serviceInfo.applicationInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004866 return res;
4867 }
4868
4869 @Override
4870 protected void sortResults(List<ResolveInfo> results) {
4871 Collections.sort(results, mResolvePrioritySorter);
4872 }
4873
4874 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004875 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004877 out.print(prefix); out.print(
4878 Integer.toHexString(System.identityHashCode(filter.service)));
4879 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004880 out.print(filter.service.getComponentShortName());
4881 out.print(" filter ");
4882 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 }
4884
4885// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4886// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4887// final List<ResolveInfo> retList = Lists.newArrayList();
4888// while (i.hasNext()) {
4889// final ResolveInfo resolveInfo = (ResolveInfo) i;
4890// if (isEnabledLP(resolveInfo.serviceInfo)) {
4891// retList.add(resolveInfo);
4892// }
4893// }
4894// return retList;
4895// }
4896
4897 // Keys are String (activity class name), values are Activity.
4898 private final HashMap<ComponentName, PackageParser.Service> mServices
4899 = new HashMap<ComponentName, PackageParser.Service>();
4900 private int mFlags;
4901 };
4902
4903 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4904 new Comparator<ResolveInfo>() {
4905 public int compare(ResolveInfo r1, ResolveInfo r2) {
4906 int v1 = r1.priority;
4907 int v2 = r2.priority;
4908 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4909 if (v1 != v2) {
4910 return (v1 > v2) ? -1 : 1;
4911 }
4912 v1 = r1.preferredOrder;
4913 v2 = r2.preferredOrder;
4914 if (v1 != v2) {
4915 return (v1 > v2) ? -1 : 1;
4916 }
4917 if (r1.isDefault != r2.isDefault) {
4918 return r1.isDefault ? -1 : 1;
4919 }
4920 v1 = r1.match;
4921 v2 = r2.match;
4922 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
Dianne Hackbornd99b2932011-08-18 14:39:58 -07004923 if (v1 != v2) {
4924 return (v1 > v2) ? -1 : 1;
4925 }
4926 if (r1.system != r2.system) {
4927 return r1.system ? -1 : 1;
4928 }
4929 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 }
4931 };
4932
4933 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4934 new Comparator<ProviderInfo>() {
4935 public int compare(ProviderInfo p1, ProviderInfo p2) {
4936 final int v1 = p1.initOrder;
4937 final int v2 = p2.initOrder;
4938 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4939 }
4940 };
4941
Kenny Root447106f2011-03-23 11:00:15 -07004942 static final void sendPackageBroadcast(String action, String pkg,
Amith Yamasani13593602012-03-22 16:16:17 -07004943 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 IActivityManager am = ActivityManagerNative.getDefault();
4945 if (am != null) {
4946 try {
Amith Yamasani13593602012-03-22 16:16:17 -07004947 int[] userIds = userId == UserId.USER_ALL
4948 ? sUserManager.getUserIds()
4949 : new int[] {userId};
4950 for (int id : userIds) {
4951 final Intent intent = new Intent(action,
4952 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4953 if (extras != null) {
4954 intent.putExtras(extras);
4955 }
4956 if (targetPkg != null) {
4957 intent.setPackage(targetPkg);
4958 }
4959 // Modify the UID when posting to other users
4960 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
4961 if (uid > 0 && id > 0) {
4962 uid = UserId.getUid(id, UserId.getAppId(uid));
4963 intent.putExtra(Intent.EXTRA_UID, uid);
4964 }
4965 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
4966 am.broadcastIntent(null, intent, null, finishedReceiver,
4967 0, null, null, null, finishedReceiver != null, false, id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 } catch (RemoteException ex) {
4970 }
4971 }
4972 }
Kenny Root300c13a2011-01-18 13:04:40 -08004973
4974 /**
4975 * Check if the external storage media is available. This is true if there
4976 * is a mounted external storage medium or if the external storage is
4977 * emulated.
4978 */
4979 private boolean isExternalMediaAvailable() {
4980 return mMediaMounted || Environment.isExternalStorageEmulated();
4981 }
4982
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004983 public String nextPackageToClean(String lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07004984 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004985 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08004986 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004987 // If the external storage is no longer mounted at this point,
4988 // the caller may not have been able to delete all of this
4989 // packages files and can not delete any more. Bail.
4990 return null;
4991 }
4992 if (lastPackage != null) {
4993 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4994 }
4995 return mSettings.mPackagesToBeCleaned.size() > 0
4996 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4997 }
4998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005000 void schedulePackageCleaning(String packageName) {
5001 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
5002 }
5003
5004 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07005005 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005006 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08005007 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005008 return;
5009 }
5010 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
5011 return;
5012 }
5013 }
5014 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
5015 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
5016 IActivityManager am = ActivityManagerNative.getDefault();
5017 if (am != null) {
5018 try {
5019 am.startService(null, intent, null);
5020 } catch (RemoteException e) {
5021 }
5022 }
5023 }
5024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 private final class AppDirObserver extends FileObserver {
5026 public AppDirObserver(String path, int mask, boolean isrom) {
5027 super(path, mask);
5028 mRootDir = path;
5029 mIsRom = isrom;
5030 }
5031
5032 public void onEvent(int event, String path) {
5033 String removedPackage = null;
5034 int removedUid = -1;
5035 String addedPackage = null;
5036 int addedUid = -1;
5037
Kenny Root447106f2011-03-23 11:00:15 -07005038 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 synchronized (mInstallLock) {
5040 String fullPathStr = null;
5041 File fullPath = null;
5042 if (path != null) {
5043 fullPath = new File(mRootDir, path);
5044 fullPathStr = fullPath.getPath();
5045 }
5046
Kenny Root9718cf52011-02-23 16:45:26 -08005047 if (DEBUG_APP_DIR_OBSERVER)
5048 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049
5050 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08005051 if (DEBUG_APP_DIR_OBSERVER)
5052 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 return;
5054 }
5055
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005056 // Ignore packages that are being installed or
5057 // have just been installed.
5058 if (ignoreCodePath(fullPathStr)) {
5059 return;
5060 }
5061 PackageParser.Package p = null;
Kenny Root447106f2011-03-23 11:00:15 -07005062 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005063 synchronized (mPackages) {
5064 p = mAppDirs.get(fullPathStr);
5065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005067 if (p != null) {
5068 removePackageLI(p, true);
5069 removedPackage = p.applicationInfo.packageName;
5070 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 }
5072 }
5073
5074 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005076 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07005077 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
5078 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005079 PackageParser.PARSE_CHATTY |
5080 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005081 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
5082 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005084 /*
5085 * TODO this seems dangerous as the package may have
5086 * changed since we last acquired the mPackages
5087 * lock.
5088 */
5089 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005091 updatePermissionsLPw(p.packageName, p,
Dianne Hackborne639da72012-02-21 15:11:13 -08005092 p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 }
5094 addedPackage = p.applicationInfo.packageName;
5095 addedUid = p.applicationInfo.uid;
5096 }
5097 }
5098 }
5099
Kenny Root447106f2011-03-23 11:00:15 -07005100 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005102 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 }
5104 }
5105
5106 if (removedPackage != null) {
5107 Bundle extras = new Bundle(1);
5108 extras.putInt(Intent.EXTRA_UID, removedUid);
5109 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005110 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005111 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
5113 if (addedPackage != null) {
5114 Bundle extras = new Bundle(1);
5115 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07005116 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07005117 extras, null, null, UserId.USER_ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 }
5119 }
5120
5121 private final String mRootDir;
5122 private final boolean mIsRom;
5123 }
Jacek Surazski65e13172009-04-28 15:26:38 +02005124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 /* Called when a downloaded package installation has been confirmed by the user */
5126 public void installPackage(
5127 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02005128 installPackage(packageURI, observer, flags, null);
5129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005130
Jacek Surazski65e13172009-04-28 15:26:38 +02005131 /* Called when a downloaded package installation has been confirmed by the user */
5132 public void installPackage(
5133 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
5134 final String installerPackageName) {
Kenny Root5ab21572011-07-27 11:11:19 -07005135 installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
5136 null);
5137 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005138
Kenny Root5ab21572011-07-27 11:11:19 -07005139 @Override
5140 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
5141 int flags, String installerPackageName, Uri verificationURI,
5142 ManifestDigest manifestDigest) {
5143 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
5144
5145 final int uid = Binder.getCallingUid();
5146
5147 final int filteredFlags;
5148
5149 if (uid == Process.SHELL_UID || uid == 0) {
5150 if (DEBUG_INSTALL) {
5151 Slog.v(TAG, "Install from ADB");
5152 }
5153 filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
5154 } else {
5155 filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
5156 }
5157
5158 final Message msg = mHandler.obtainMessage(INIT_COPY);
5159 msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
5160 verificationURI, manifestDigest);
5161 mHandler.sendMessage(msg);
5162 }
5163
5164 @Override
Kenny Root05ca4c92011-09-15 10:36:25 -07005165 public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
Kenny Root5ab21572011-07-27 11:11:19 -07005166 final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
Kenny Root05ca4c92011-09-15 10:36:25 -07005167 final PackageVerificationResponse response = new PackageVerificationResponse(
5168 verificationCode, Binder.getCallingUid());
Kenny Root5ab21572011-07-27 11:11:19 -07005169 msg.arg1 = id;
Kenny Root05ca4c92011-09-15 10:36:25 -07005170 msg.obj = response;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005171 mHandler.sendMessage(msg);
5172 }
5173
Kenny Root05ca4c92011-09-15 10:36:25 -07005174 private ComponentName matchComponentForVerifier(String packageName,
5175 List<ResolveInfo> receivers) {
5176 ActivityInfo targetReceiver = null;
5177
5178 final int NR = receivers.size();
5179 for (int i = 0; i < NR; i++) {
5180 final ResolveInfo info = receivers.get(i);
5181 if (info.activityInfo == null) {
5182 continue;
5183 }
5184
5185 if (packageName.equals(info.activityInfo.packageName)) {
5186 targetReceiver = info.activityInfo;
5187 break;
5188 }
5189 }
5190
5191 if (targetReceiver == null) {
5192 return null;
5193 }
5194
5195 return new ComponentName(targetReceiver.packageName, targetReceiver.name);
5196 }
5197
5198 private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
5199 List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
5200 if (pkgInfo.verifiers.length == 0) {
5201 return null;
5202 }
5203
5204 final int N = pkgInfo.verifiers.length;
5205 final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
5206 for (int i = 0; i < N; i++) {
5207 final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
5208
5209 final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
5210 receivers);
5211 if (comp == null) {
5212 continue;
5213 }
5214
5215 final int verifierUid = getUidForVerifier(verifierInfo);
5216 if (verifierUid == -1) {
5217 continue;
5218 }
5219
5220 if (DEBUG_VERIFY) {
5221 Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
5222 + " with the correct signature");
5223 }
5224 sufficientVerifiers.add(comp);
5225 verificationState.addSufficientVerifier(verifierUid);
5226 }
5227
5228 return sufficientVerifiers;
5229 }
5230
5231 private int getUidForVerifier(VerifierInfo verifierInfo) {
5232 synchronized (mPackages) {
5233 final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
5234 if (pkg == null) {
5235 return -1;
5236 } else if (pkg.mSignatures.length != 1) {
5237 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5238 + " has more than one signature; ignoring");
5239 return -1;
5240 }
5241
5242 /*
5243 * If the public key of the package's signature does not match
5244 * our expected public key, then this is a different package and
5245 * we should skip.
5246 */
5247
5248 final byte[] expectedPublicKey;
5249 try {
5250 final Signature verifierSig = pkg.mSignatures[0];
5251 final PublicKey publicKey = verifierSig.getPublicKey();
5252 expectedPublicKey = publicKey.getEncoded();
5253 } catch (CertificateException e) {
5254 return -1;
5255 }
5256
5257 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
5258
5259 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
5260 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
5261 + " does not have the expected public key; ignoring");
5262 return -1;
5263 }
5264
5265 return pkg.applicationInfo.uid;
5266 }
5267 }
5268
Christopher Tate1bb69062010-02-19 17:02:12 -08005269 public void finishPackageInstall(int token) {
Kenny Root461ff1f2011-08-09 09:43:03 -07005270 enforceSystemOrRoot("Only the system is allowed to finish installs");
5271
5272 if (DEBUG_INSTALL) {
5273 Slog.v(TAG, "BM finishing package install for " + token);
5274 }
5275
5276 final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
Christopher Tate1bb69062010-02-19 17:02:12 -08005277 mHandler.sendMessage(msg);
5278 }
5279
Kenny Root5ab21572011-07-27 11:11:19 -07005280 /**
5281 * Get the verification agent timeout.
5282 *
5283 * @return verification timeout in milliseconds
5284 */
5285 private long getVerificationTimeout() {
5286 return android.provider.Settings.Secure.getLong(mContext.getContentResolver(),
5287 android.provider.Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
5288 DEFAULT_VERIFICATION_TIMEOUT);
5289 }
5290
5291 /**
5292 * Check whether or not package verification has been enabled.
5293 *
5294 * @return true if verification should be performed
5295 */
5296 private boolean isVerificationEnabled() {
5297 return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
5298 android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
5299 DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
5300 }
5301
Kenny Rootf03b45f2011-02-23 17:25:45 -08005302 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08005303 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07005304 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08005305 synchronized (mPackages) {
5306 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
5307 if (targetPackageSetting == null) {
5308 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
5309 }
5310
5311 PackageSetting installerPackageSetting;
5312 if (installerPackageName != null) {
5313 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
5314 if (installerPackageSetting == null) {
5315 throw new IllegalArgumentException("Unknown installer package: "
5316 + installerPackageName);
5317 }
5318 } else {
5319 installerPackageSetting = null;
5320 }
5321
5322 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07005323 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08005324 if (obj != null) {
5325 if (obj instanceof SharedUserSetting) {
5326 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
5327 } else if (obj instanceof PackageSetting) {
5328 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
5329 } else {
5330 throw new SecurityException("Bad object " + obj + " for uid " + uid);
5331 }
5332 } else {
5333 throw new SecurityException("Unknown calling uid " + uid);
5334 }
5335
5336 // Verify: can't set installerPackageName to a package that is
5337 // not signed with the same cert as the caller.
5338 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005339 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005340 installerPackageSetting.signatures.mSignatures)
5341 != PackageManager.SIGNATURE_MATCH) {
5342 throw new SecurityException(
5343 "Caller does not have same cert as new installer package "
5344 + installerPackageName);
5345 }
5346 }
5347
5348 // Verify: if target already has an installer package, it must
5349 // be signed with the same cert as the caller.
5350 if (targetPackageSetting.installerPackageName != null) {
5351 PackageSetting setting = mSettings.mPackages.get(
5352 targetPackageSetting.installerPackageName);
5353 // If the currently set package isn't valid, then it's always
5354 // okay to change it.
5355 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07005356 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08005357 setting.signatures.mSignatures)
5358 != PackageManager.SIGNATURE_MATCH) {
5359 throw new SecurityException(
5360 "Caller does not have same cert as old installer package "
5361 + targetPackageSetting.installerPackageName);
5362 }
5363 }
5364 }
5365
5366 // Okay!
5367 targetPackageSetting.installerPackageName = installerPackageName;
5368 scheduleWriteSettingsLocked();
5369 }
5370 }
5371
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005372 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 // Queue up an async operation since the package installation may take a little while.
5374 mHandler.post(new Runnable() {
5375 public void run() {
5376 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005377 // Result object to be returned
5378 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005379 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005380 res.uid = -1;
5381 res.pkg = null;
5382 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005383 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005384 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005385 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005386 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005387 }
Kenny Root6dceb882012-04-12 14:23:49 -07005388 args.doPostInstall(res.returnCode, res.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005389 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005390
5391 // A restore should be performed at this point if (a) the install
5392 // succeeded, (b) the operation is not an update, and (c) the new
5393 // package has a backupAgent defined.
5394 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08005395 boolean doRestore = (!update
5396 && res.pkg != null
5397 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08005398
5399 // Set up the post-install work request bookkeeping. This will be used
5400 // and cleaned up by the post-install event handling regardless of whether
5401 // there's a restore pass performed. Token values are >= 1.
5402 int token;
5403 if (mNextInstallToken < 0) mNextInstallToken = 1;
5404 token = mNextInstallToken++;
5405
5406 PostInstallData data = new PostInstallData(args, res);
5407 mRunningInstalls.put(token, data);
5408 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
5409
5410 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
5411 // Pass responsibility to the Backup Manager. It will perform a
5412 // restore if appropriate, then pass responsibility back to the
5413 // Package Manager to run the post-install observer callbacks
5414 // and broadcasts.
5415 IBackupManager bm = IBackupManager.Stub.asInterface(
5416 ServiceManager.getService(Context.BACKUP_SERVICE));
5417 if (bm != null) {
5418 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
5419 + " to BM for possible restore");
5420 try {
5421 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
5422 } catch (RemoteException e) {
5423 // can't happen; the backup manager is local
5424 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005425 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08005426 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005427 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005428 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005429 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08005430 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 }
Christopher Tate1bb69062010-02-19 17:02:12 -08005433
5434 if (!doRestore) {
5435 // No restore possible, or the Backup Manager was mysteriously not
5436 // available -- just fire the post-install work request directly.
5437 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
5438 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
5439 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 }
5442 });
5443 }
5444
Kenny Root5ab21572011-07-27 11:11:19 -07005445 private abstract class HandlerParams {
5446 private static final int MAX_RETRIES = 4;
5447
5448 /**
5449 * Number of times startCopy() has been attempted and had a non-fatal
5450 * error.
5451 */
5452 private int mRetries = 0;
5453
Dianne Hackborn7d608422011-08-07 16:24:18 -07005454 final boolean startCopy() {
5455 boolean res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005456 try {
Kenny Root5ab21572011-07-27 11:11:19 -07005457 if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
5458
5459 if (++mRetries > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005460 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005461 mHandler.sendEmptyMessage(MCS_GIVE_UP);
5462 handleServiceError();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005463 return false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005464 } else {
5465 handleStartCopy();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005466 res = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005467 }
5468 } catch (RemoteException e) {
Kenny Root5ab21572011-07-27 11:11:19 -07005469 if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005470 mHandler.sendEmptyMessage(MCS_RECONNECT);
Dianne Hackborn7d608422011-08-07 16:24:18 -07005471 res = false;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005472 }
5473 handleReturnCode();
Dianne Hackborn7d608422011-08-07 16:24:18 -07005474 return res;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005475 }
5476
5477 final void serviceError() {
Kenny Root5ab21572011-07-27 11:11:19 -07005478 if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005479 handleServiceError();
5480 handleReturnCode();
5481 }
Kenny Root5ab21572011-07-27 11:11:19 -07005482
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005483 abstract void handleStartCopy() throws RemoteException;
5484 abstract void handleServiceError();
5485 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005486 }
5487
Kenny Root366949c2011-01-14 17:18:14 -08005488 class MeasureParams extends HandlerParams {
5489 private final PackageStats mStats;
5490 private boolean mSuccess;
5491
5492 private final IPackageStatsObserver mObserver;
5493
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07005494 public MeasureParams(PackageStats stats, boolean success, IPackageStatsObserver observer) {
Kenny Root366949c2011-01-14 17:18:14 -08005495 mObserver = observer;
5496 mStats = stats;
5497 mSuccess = success;
5498 }
5499
5500 @Override
5501 void handleStartCopy() throws RemoteException {
5502 final boolean mounted;
5503
5504 if (Environment.isExternalStorageEmulated()) {
5505 mounted = true;
5506 } else {
5507 final String status = Environment.getExternalStorageState();
5508
5509 mounted = status.equals(Environment.MEDIA_MOUNTED)
5510 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
5511 }
5512
5513 if (mounted) {
5514 final File externalCacheDir = Environment
5515 .getExternalStorageAppCacheDirectory(mStats.packageName);
5516 final long externalCacheSize = mContainerService
5517 .calculateDirectorySize(externalCacheDir.getPath());
5518 mStats.externalCacheSize = externalCacheSize;
5519
5520 final File externalDataDir = Environment
5521 .getExternalStorageAppDataDirectory(mStats.packageName);
5522 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
5523 .getPath());
5524
5525 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
5526 externalDataSize -= externalCacheSize;
5527 }
5528 mStats.externalDataSize = externalDataSize;
5529
5530 final File externalMediaDir = Environment
5531 .getExternalStorageAppMediaDirectory(mStats.packageName);
5532 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08005533 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08005534
5535 final File externalObbDir = Environment
5536 .getExternalStorageAppObbDirectory(mStats.packageName);
5537 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
5538 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08005539 }
5540 }
5541
5542 @Override
5543 void handleReturnCode() {
5544 if (mObserver != null) {
5545 try {
5546 mObserver.onGetStatsCompleted(mStats, mSuccess);
5547 } catch (RemoteException e) {
5548 Slog.i(TAG, "Observer no longer exists.");
5549 }
5550 }
5551 }
5552
5553 @Override
5554 void handleServiceError() {
5555 Slog.e(TAG, "Could not measure application " + mStats.packageName
5556 + " external storage");
5557 }
5558 }
5559
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005560 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005561 final IPackageInstallObserver observer;
5562 int flags;
5563 final Uri packageURI;
5564 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005565 final Uri verificationURI;
5566 final ManifestDigest manifestDigest;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005567 private InstallArgs mArgs;
5568 private int mRet;
Kenny Root5ab21572011-07-27 11:11:19 -07005569
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005570 InstallParams(Uri packageURI,
5571 IPackageInstallObserver observer, int flags,
Kenny Root5ab21572011-07-27 11:11:19 -07005572 String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005573 this.packageURI = packageURI;
5574 this.flags = flags;
5575 this.observer = observer;
5576 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005577 this.verificationURI = verificationURI;
5578 this.manifestDigest = manifestDigest;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005579 }
5580
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005581 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
5582 String packageName = pkgLite.packageName;
5583 int installLocation = pkgLite.installLocation;
5584 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07005585 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005586 synchronized (mPackages) {
5587 PackageParser.Package pkg = mPackages.get(packageName);
5588 if (pkg != null) {
5589 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5590 // Check for updated system application.
5591 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5592 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005593 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005594 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
5595 }
5596 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5597 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005598 if (onSd) {
5599 // Install flag overrides everything.
5600 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5601 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005602 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005603 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
5604 // Application explicitly specified internal.
5605 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
5606 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
5607 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005608 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005609 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07005610 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07005611 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5612 }
5613 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005614 }
5615 }
5616 } else {
5617 // Invalid install. Return error code
5618 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
5619 }
5620 }
5621 }
5622 // All the special cases have been taken care of.
5623 // Return result based on recommended install location.
5624 if (onSd) {
5625 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
5626 }
5627 return pkgLite.recommendedInstallLocation;
5628 }
5629
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005630 /*
5631 * Invoke remote method to get package information and install
5632 * location values. Override install location based on default
5633 * policy if needed and then create install arguments based
5634 * on the install location.
5635 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005636 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08005637 int ret = PackageManager.INSTALL_SUCCEEDED;
Kenny Root05ca4c92011-09-15 10:36:25 -07005638 final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
5639 final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
5640 PackageInfoLite pkgLite = null;
5641
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005642 if (onInt && onSd) {
5643 // Check if both bits are set.
5644 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
5645 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005646 } else {
Kenny Root62e1b4e2011-03-14 17:13:39 -07005647 final long lowThreshold;
5648
5649 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
5650 .getService(DeviceStorageMonitorService.SERVICE);
5651 if (dsm == null) {
5652 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
5653 lowThreshold = 0L;
5654 } else {
5655 lowThreshold = dsm.getMemoryLowThreshold();
5656 }
5657
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005658 // Remote call to find out default install location
Kenny Root11128572010-10-11 10:51:32 -07005659 try {
5660 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5661 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root62e1b4e2011-03-14 17:13:39 -07005662 pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags,
5663 lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07005664 } finally {
5665 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5666 }
5667
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005668 int loc = pkgLite.recommendedInstallLocation;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005669 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005670 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005671 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005672 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005673 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005674 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5675 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
5676 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Kenny Root1ebd74a2011-08-03 15:09:44 -07005677 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
5678 ret = PackageManager.INSTALL_FAILED_INVALID_URI;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005679 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
Kenny Root1ebd74a2011-08-03 15:09:44 -07005680 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005681 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005682 // Override with defaults if needed.
5683 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005684 if (!onSd && !onInt) {
5685 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005686 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
5687 // Set the flag to install on external media.
5688 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005689 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005690 } else {
5691 // Make sure the flag for installing on external
5692 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005693 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005694 flags &= ~PackageManager.INSTALL_EXTERNAL;
5695 }
5696 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005697 }
5698 }
Kenny Root5ab21572011-07-27 11:11:19 -07005699
5700 final InstallArgs args = createInstallArgs(this);
Kenny Root05ca4c92011-09-15 10:36:25 -07005701 mArgs = args;
5702
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005703 if (ret == PackageManager.INSTALL_SUCCEEDED) {
Kenny Root5ab21572011-07-27 11:11:19 -07005704 /*
5705 * Determine if we have any installed package verifiers. If we
5706 * do, then we'll defer to them to verify the packages.
5707 */
Kenny Root05ca4c92011-09-15 10:36:25 -07005708 final int requiredUid = mRequiredVerifierPackage == null ? -1
Amith Yamasani483f3b02012-03-13 16:08:00 -07005709 : getPackageUid(mRequiredVerifierPackage, 0);
Kenny Root05ca4c92011-09-15 10:36:25 -07005710 if (requiredUid != -1 && isVerificationEnabled()) {
Kenny Roota503a0f2011-10-03 14:45:28 -07005711 final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
5712 verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
Kenny Root05ca4c92011-09-15 10:36:25 -07005713 verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root5ab21572011-07-27 11:11:19 -07005714
Kenny Root05ca4c92011-09-15 10:36:25 -07005715 final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
Amith Yamasani483f3b02012-03-13 16:08:00 -07005716 PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
Kenny Root05ca4c92011-09-15 10:36:25 -07005717
5718 if (DEBUG_VERIFY) {
Kenny Root5ab21572011-07-27 11:11:19 -07005719 Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
Kenny Root05ca4c92011-09-15 10:36:25 -07005720 + verification.toString() + " with " + pkgLite.verifiers.length
5721 + " optional verifiers");
Kenny Root5ab21572011-07-27 11:11:19 -07005722 }
5723
5724 final int verificationId = mPendingVerificationToken++;
5725
5726 verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
5727
5728 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
5729 installerPackageName);
5730
5731 verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
5732
5733 if (verificationURI != null) {
5734 verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
5735 verificationURI);
5736 }
5737
Kenny Root05ca4c92011-09-15 10:36:25 -07005738 final PackageVerificationState verificationState = new PackageVerificationState(
5739 requiredUid, args);
5740
5741 mPendingVerification.append(verificationId, verificationState);
5742
5743 final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
5744 receivers, verificationState);
Kenny Root5ab21572011-07-27 11:11:19 -07005745
5746 /*
Kenny Root05ca4c92011-09-15 10:36:25 -07005747 * If any sufficient verifiers were listed in the package
5748 * manifest, attempt to ask them.
Kenny Root5ab21572011-07-27 11:11:19 -07005749 */
Kenny Root05ca4c92011-09-15 10:36:25 -07005750 if (sufficientVerifiers != null) {
5751 final int N = sufficientVerifiers.size();
5752 if (N == 0) {
5753 Slog.i(TAG, "Additional verifiers required, but none installed.");
5754 ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
5755 } else {
5756 for (int i = 0; i < N; i++) {
5757 final ComponentName verifierComponent = sufficientVerifiers.get(i);
5758
5759 final Intent sufficientIntent = new Intent(verification);
5760 sufficientIntent.setComponent(verifierComponent);
5761
5762 mContext.sendBroadcast(sufficientIntent);
5763 }
5764 }
5765 }
5766
5767 final ComponentName requiredVerifierComponent = matchComponentForVerifier(
5768 mRequiredVerifierPackage, receivers);
5769 if (ret == PackageManager.INSTALL_SUCCEEDED
5770 && mRequiredVerifierPackage != null) {
5771 /*
5772 * Send the intent to the required verification agent,
5773 * but only start the verification timeout after the
5774 * target BroadcastReceivers have run.
5775 */
5776 verification.setComponent(requiredVerifierComponent);
5777 mContext.sendOrderedBroadcast(verification,
5778 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
5779 new BroadcastReceiver() {
5780 @Override
5781 public void onReceive(Context context, Intent intent) {
5782 final Message msg = mHandler
5783 .obtainMessage(CHECK_PENDING_VERIFICATION);
5784 msg.arg1 = verificationId;
5785 mHandler.sendMessageDelayed(msg, getVerificationTimeout());
5786 }
5787 }, null, 0, null, null);
5788
5789 /*
5790 * We don't want the copy to proceed until verification
5791 * succeeds, so null out this field.
5792 */
5793 mArgs = null;
5794 }
Kenny Root5ab21572011-07-27 11:11:19 -07005795 } else {
Kenny Root05ca4c92011-09-15 10:36:25 -07005796 /*
5797 * No package verification is enabled, so immediately start
5798 * the remote call to initiate copy using temporary file.
5799 */
Kenny Root5ab21572011-07-27 11:11:19 -07005800 ret = args.copyApk(mContainerService, true);
5801 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005802 }
Kenny Root5ab21572011-07-27 11:11:19 -07005803
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005804 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005805 }
5806
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005807 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005808 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07005809 // If mArgs is null, then MCS couldn't be reached. When it
5810 // reconnects, it will try again to install. At that point, this
5811 // will succeed.
5812 if (mArgs != null) {
5813 processPendingInstall(mArgs, mRet);
5814 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005815 }
5816
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005817 @Override
5818 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005819 mArgs = createInstallArgs(this);
5820 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005821 }
Kenny Root6dceb882012-04-12 14:23:49 -07005822
5823 public boolean isForwardLocked() {
5824 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5825 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005826 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005827
5828 /*
5829 * Utility class used in movePackage api.
5830 * srcArgs and targetArgs are not set for invalid flags and make
5831 * sure to do null checks when invoking methods on them.
5832 * We probably want to return ErrorPrams for both failed installs
5833 * and moves.
5834 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005835 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005836 final IPackageMoveObserver observer;
5837 final int flags;
5838 final String packageName;
5839 final InstallArgs srcArgs;
5840 final InstallArgs targetArgs;
Kenny Root6dceb882012-04-12 14:23:49 -07005841 int uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005842 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07005843
5844 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
Kenny Root6dceb882012-04-12 14:23:49 -07005845 String packageName, String dataDir, int uid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005846 this.srcArgs = srcArgs;
5847 this.observer = observer;
5848 this.flags = flags;
5849 this.packageName = packageName;
Kenny Root6dceb882012-04-12 14:23:49 -07005850 this.uid = uid;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005851 if (srcArgs != null) {
5852 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07005853 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005854 } else {
5855 targetArgs = null;
5856 }
5857 }
5858
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005859 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005860 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5861 // Check for storage space on target medium
5862 if (!targetArgs.checkFreeStorage(mContainerService)) {
5863 Log.w(TAG, "Insufficient storage to install");
5864 return;
5865 }
Kenny Rootbf023582012-05-02 16:56:15 -07005866
5867 mRet = srcArgs.doPreCopy();
5868 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
5869 return;
5870 }
5871
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005872 mRet = targetArgs.copyApk(mContainerService, false);
Kenny Rootbf023582012-05-02 16:56:15 -07005873 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
5874 srcArgs.doPostCopy(uid);
5875 return;
5876 }
5877
5878 mRet = srcArgs.doPostCopy(uid);
5879 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
5880 return;
5881 }
5882
5883 mRet = targetArgs.doPreInstall(mRet);
5884 if (mRet != PackageManager.INSTALL_SUCCEEDED) {
5885 return;
5886 }
5887
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005888 if (DEBUG_SD_INSTALL) {
5889 StringBuilder builder = new StringBuilder();
5890 if (srcArgs != null) {
5891 builder.append("src: ");
5892 builder.append(srcArgs.getCodePath());
5893 }
5894 if (targetArgs != null) {
5895 builder.append(" target : ");
5896 builder.append(targetArgs.getCodePath());
5897 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005898 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005899 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005900 }
5901
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005902 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005903 void handleReturnCode() {
Kenny Root6dceb882012-04-12 14:23:49 -07005904 targetArgs.doPostInstall(mRet, uid);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005905 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
5906 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
5907 currentStatus = PackageManager.MOVE_SUCCEEDED;
5908 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
5909 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
5910 }
5911 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005912 }
5913
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005914 @Override
5915 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005916 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005917 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005918 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005919
Kenny Root6dceb882012-04-12 14:23:49 -07005920 /**
5921 * Used during creation of InstallArgs
5922 *
5923 * @param flags package installation flags
5924 * @return true if should be installed on external storage
5925 */
5926 private static boolean installOnSd(int flags) {
5927 if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
5928 return false;
5929 }
5930 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
5931 return true;
5932 }
5933 return false;
5934 }
5935
5936 /**
5937 * Used during creation of InstallArgs
5938 *
5939 * @param flags package installation flags
5940 * @return true if should be installed as forward locked
5941 */
5942 private static boolean installForwardLocked(int flags) {
5943 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5944 }
5945
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005946 private InstallArgs createInstallArgs(InstallParams params) {
Kenny Root6dceb882012-04-12 14:23:49 -07005947 if (installOnSd(params.flags) || params.isForwardLocked()) {
5948 return new AsecInstallArgs(params);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005949 } else {
5950 return new FileInstallArgs(params);
5951 }
5952 }
5953
Kenny Root85387d72010-08-26 10:13:11 -07005954 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
5955 String nativeLibraryPath) {
Kenny Root6dceb882012-04-12 14:23:49 -07005956 if (installOnSd(flags) || installForwardLocked(flags)) {
5957 return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07005958 installOnSd(flags), installForwardLocked(flags));
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005959 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005960 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005961 }
5962 }
5963
Kenny Root85387d72010-08-26 10:13:11 -07005964 // Used by package mover
5965 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Kenny Root6dceb882012-04-12 14:23:49 -07005966 if (installOnSd(flags) || installForwardLocked(flags)) {
Kenny Rootbf023582012-05-02 16:56:15 -07005967 String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
5968 + AsecInstallArgs.RES_FILE_NAME);
5969 return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
5970 installForwardLocked(flags));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005971 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005972 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005973 }
5974 }
5975
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005976 static abstract class InstallArgs {
5977 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005978 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005979 final int flags;
5980 final Uri packageURI;
5981 final String installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005982 final ManifestDigest manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005983
Kenny Root5ab21572011-07-27 11:11:19 -07005984 InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
5985 String installerPackageName, ManifestDigest manifestDigest) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005986 this.packageURI = packageURI;
5987 this.flags = flags;
5988 this.observer = observer;
5989 this.installerPackageName = installerPackageName;
Kenny Root5ab21572011-07-27 11:11:19 -07005990 this.manifestDigest = manifestDigest;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005991 }
5992
5993 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005994 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005995 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005996 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Kenny Root6dceb882012-04-12 14:23:49 -07005997
5998 abstract int doPostInstall(int status, int uid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005999 abstract String getCodePath();
6000 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07006001 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006002 // Need installer lock especially for dex file removal.
6003 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006004 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006005 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Kenny Root6dceb882012-04-12 14:23:49 -07006006
Kenny Rootbf023582012-05-02 16:56:15 -07006007 /**
6008 * Called before the source arguments are copied. This is used mostly
6009 * for MoveParams when it needs to read the source file to put it in the
6010 * destination.
6011 */
6012 int doPreCopy() {
6013 return PackageManager.INSTALL_SUCCEEDED;
6014 }
6015
6016 /**
6017 * Called after the source arguments are copied. This is used mostly for
6018 * MoveParams when it needs to read the source file to put it in the
6019 * destination.
6020 *
6021 * @return
6022 */
6023 int doPostCopy(int uid) {
6024 return PackageManager.INSTALL_SUCCEEDED;
6025 }
6026
Kenny Root6dceb882012-04-12 14:23:49 -07006027 protected boolean isFwdLocked() {
6028 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
6029 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006030 }
6031
6032 class FileInstallArgs extends InstallArgs {
6033 File installDir;
6034 String codeFileName;
6035 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07006036 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006037 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006038
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006039 FileInstallArgs(InstallParams params) {
Kenny Root5ab21572011-07-27 11:11:19 -07006040 super(params.packageURI, params.observer, params.flags, params.installerPackageName,
6041 params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006042 }
6043
Kenny Root85387d72010-08-26 10:13:11 -07006044 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Kenny Root5ab21572011-07-27 11:11:19 -07006045 super(null, null, 0, null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006046 File codeFile = new File(fullCodePath);
6047 installDir = codeFile.getParentFile();
6048 codeFileName = fullCodePath;
6049 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006050 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006051 }
6052
Kenny Root85387d72010-08-26 10:13:11 -07006053 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Kenny Root5ab21572011-07-27 11:11:19 -07006054 super(packageURI, null, 0, null, null);
Kenny Root85387d72010-08-26 10:13:11 -07006055 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006056 String apkName = getNextCodePath(null, pkgName, ".apk");
6057 codeFileName = new File(installDir, apkName + ".apk").getPath();
6058 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07006059 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006060 }
6061
Kenny Root11128572010-10-11 10:51:32 -07006062 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07006063 final long lowThreshold;
6064
6065 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
6066 .getService(DeviceStorageMonitorService.SERVICE);
6067 if (dsm == null) {
6068 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
6069 lowThreshold = 0L;
6070 } else {
6071 if (dsm.isMemoryLow()) {
6072 Log.w(TAG, "Memory is reported as being too low; aborting package install");
6073 return false;
6074 }
6075
6076 lowThreshold = dsm.getMemoryLowThreshold();
6077 }
6078
Kenny Root11128572010-10-11 10:51:32 -07006079 try {
6080 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6081 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006082 return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07006083 } finally {
6084 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6085 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08006086 }
6087
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006088 String getCodePath() {
6089 return codeFileName;
6090 }
6091
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006092 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07006093 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006094 codeFileName = createTempPackageFile(installDir).getPath();
6095 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006096 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006097 }
6098
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006099 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006100 if (temp) {
6101 // Generate temp file name
6102 createCopyFile();
6103 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006104 // Get a ParcelFileDescriptor to write to the output file
6105 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006106 if (!created) {
6107 try {
6108 codeFile.createNewFile();
6109 // Set permissions
6110 if (!setPermissions()) {
6111 // Failed setting permissions.
6112 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6113 }
6114 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006115 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006116 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6117 }
6118 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006119 ParcelFileDescriptor out = null;
6120 try {
Kenny Root85387d72010-08-26 10:13:11 -07006121 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006122 } catch (FileNotFoundException e) {
Kenny Rootf5121a92011-08-10 16:23:32 -07006123 Slog.e(TAG, "Failed to create file descriptor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006124 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6125 }
6126 // Copy the resource now
6127 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6128 try {
Kenny Root11128572010-10-11 10:51:32 -07006129 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6130 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Rootf5121a92011-08-10 16:23:32 -07006131 ret = imcs.copyResource(packageURI, out);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006132 } finally {
Kenny Root2782a472012-04-14 21:48:21 -07006133 IoUtils.closeQuietly(out);
Kenny Root11128572010-10-11 10:51:32 -07006134 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006135 }
Kenny Root85387d72010-08-26 10:13:11 -07006136
Kenny Root2782a472012-04-14 21:48:21 -07006137 if (isFwdLocked()) {
6138 final File destResourceFile = new File(getResourcePath());
6139
6140 // Copy the public files
6141 try {
6142 PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
6143 } catch (IOException e) {
6144 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
6145 + " forward-locked app.");
6146 destResourceFile.delete();
6147 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6148 }
6149 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006150 return ret;
6151 }
6152
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006153 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006154 if (status != PackageManager.INSTALL_SUCCEEDED) {
6155 cleanUp();
6156 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006157 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006158 }
6159
6160 boolean doRename(int status, final String pkgName, String oldCodePath) {
6161 if (status != PackageManager.INSTALL_SUCCEEDED) {
6162 cleanUp();
6163 return false;
6164 } else {
Kenny Root2782a472012-04-14 21:48:21 -07006165 final File oldCodeFile = new File(getCodePath());
6166 final File oldResourceFile = new File(getResourcePath());
6167
6168 // Rename APK file based on packageName
6169 final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
6170 final File newCodeFile = new File(installDir, apkName + ".apk");
6171 if (!oldCodeFile.renameTo(newCodeFile)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006172 return false;
6173 }
Kenny Root2782a472012-04-14 21:48:21 -07006174 codeFileName = newCodeFile.getPath();
6175
6176 // Rename public resource file if it's forward-locked.
6177 final File newResFile = new File(getResourcePathFromCodePath());
6178 if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
6179 return false;
6180 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006181 resourceFileName = getResourcePathFromCodePath();
Kenny Root2782a472012-04-14 21:48:21 -07006182
6183 // Attempt to set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006184 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006185 return false;
6186 }
Kenny Root2782a472012-04-14 21:48:21 -07006187
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006188 return true;
6189 }
6190 }
6191
Kenny Root6dceb882012-04-12 14:23:49 -07006192 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006193 if (status != PackageManager.INSTALL_SUCCEEDED) {
6194 cleanUp();
6195 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006196 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006197 }
6198
6199 String getResourcePath() {
6200 return resourceFileName;
6201 }
6202
Kenny Root2782a472012-04-14 21:48:21 -07006203 private String getResourcePathFromCodePath() {
6204 final String codePath = getCodePath();
6205 if (isFwdLocked()) {
6206 final StringBuilder sb = new StringBuilder();
6207
6208 sb.append(mAppInstallDir.getPath());
6209 sb.append('/');
6210 sb.append(getApkName(codePath));
6211 sb.append(".zip");
6212
6213 /*
6214 * If our APK is a temporary file, mark the resource as a
6215 * temporary file as well so it can be cleaned up after
6216 * catastrophic failure.
6217 */
6218 if (codePath.endsWith(".tmp")) {
6219 sb.append(".tmp");
6220 }
6221
6222 return sb.toString();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006223 } else {
6224 return codePath;
6225 }
6226 }
6227
Kenny Root85387d72010-08-26 10:13:11 -07006228 @Override
6229 String getNativeLibraryPath() {
6230 return libraryPath;
6231 }
6232
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006233 private boolean cleanUp() {
6234 boolean ret = true;
6235 String sourceDir = getCodePath();
6236 String publicSourceDir = getResourcePath();
6237 if (sourceDir != null) {
6238 File sourceFile = new File(sourceDir);
6239 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006240 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006241 ret = false;
6242 }
6243 // Delete application's code and resources
6244 sourceFile.delete();
6245 }
6246 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
6247 final File publicSourceFile = new File(publicSourceDir);
6248 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006249 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006250 }
6251 if (publicSourceFile.exists()) {
6252 publicSourceFile.delete();
6253 }
6254 }
6255 return ret;
6256 }
6257
6258 void cleanUpResourcesLI() {
6259 String sourceDir = getCodePath();
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006260 if (cleanUp()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006261 int retCode = mInstaller.rmdex(sourceDir);
6262 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006263 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006264 + " at location "
6265 + sourceDir + ", retcode=" + retCode);
6266 // we don't consider this to be a failure of the core package deletion
6267 }
6268 }
6269 }
6270
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006271 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006272 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07006273 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006274 final int filePermissions =
6275 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
6276 |FileUtils.S_IROTH;
6277 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
6278 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006279 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006280 getCodePath()
6281 + ". The return code was: " + retCode);
6282 // TODO Define new internal error
6283 return false;
6284 }
6285 return true;
6286 }
6287 return true;
6288 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006289
6290 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07006291 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006292 cleanUpResourcesLI();
6293 return true;
6294 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006295 }
6296
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07006297 /**
6298 * Extract the MountService "container ID" from the full code path of an
6299 * .apk.
6300 */
6301 static String cidFromCodePath(String fullCodePath) {
6302 int eidx = fullCodePath.lastIndexOf("/");
6303 String subStr1 = fullCodePath.substring(0, eidx);
6304 int sidx = subStr1.lastIndexOf("/");
6305 return subStr1.substring(sidx+1, eidx);
6306 }
6307
Kenny Root6dceb882012-04-12 14:23:49 -07006308 class AsecInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006309 static final String RES_FILE_NAME = "pkg.apk";
Kenny Root6dceb882012-04-12 14:23:49 -07006310 static final String PUBLIC_RES_FILE_NAME = "res.zip";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006311
Kenny Root85387d72010-08-26 10:13:11 -07006312 String cid;
6313 String packagePath;
Kenny Root6dceb882012-04-12 14:23:49 -07006314 String resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006315 String libraryPath;
6316
Kenny Root6dceb882012-04-12 14:23:49 -07006317 AsecInstallArgs(InstallParams params) {
Kenny Root5ab21572011-07-27 11:11:19 -07006318 super(params.packageURI, params.observer, params.flags, params.installerPackageName,
6319 params.manifestDigest);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006320 }
6321
Kenny Root6dceb882012-04-12 14:23:49 -07006322 AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
Kenny Rootbf023582012-05-02 16:56:15 -07006323 boolean isExternal, boolean isForwardLocked) {
6324 super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6325 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006326 // Extract cid from fullCodePath
6327 int eidx = fullCodePath.lastIndexOf("/");
6328 String subStr1 = fullCodePath.substring(0, eidx);
6329 int sidx = subStr1.lastIndexOf("/");
6330 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07006331 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006332 }
6333
Kenny Root6dceb882012-04-12 14:23:49 -07006334 AsecInstallArgs(String cid) {
6335 super(null, null, 0, null, null);
Dianne Hackbornaa77de12010-05-14 22:33:54 -07006336 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07006337 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006338 }
6339
Kenny Rootbf023582012-05-02 16:56:15 -07006340 AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
6341 super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
6342 | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006343 this.cid = cid;
6344 }
6345
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006346 void createCopyFile() {
6347 cid = getTempContainerId();
6348 }
6349
Kenny Root11128572010-10-11 10:51:32 -07006350 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
6351 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.checkExternalFreeStorage(packageURI, isFwdLocked());
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
Kenny Root6dceb882012-04-12 14:23:49 -07006360 private final boolean isExternal() {
6361 return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
6362 }
6363
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006364 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006365 if (temp) {
6366 createCopyFile();
Kenny Rootf5121a92011-08-10 16:23:32 -07006367 } else {
6368 /*
6369 * Pre-emptively destroy the container since it's destroyed if
6370 * copying fails due to it existing anyway.
6371 */
6372 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006373 }
Kenny Root11128572010-10-11 10:51:32 -07006374
6375 final String newCachePath;
6376 try {
6377 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
6378 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root6dceb882012-04-12 14:23:49 -07006379 newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
6380 RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
Kenny Root11128572010-10-11 10:51:32 -07006381 } finally {
6382 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
6383 }
6384
Kenny Root85387d72010-08-26 10:13:11 -07006385 if (newCachePath != null) {
6386 setCachePath(newCachePath);
6387 return PackageManager.INSTALL_SUCCEEDED;
6388 } else {
6389 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6390 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006391 }
6392
6393 @Override
6394 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07006395 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006396 }
6397
6398 @Override
6399 String getResourcePath() {
Kenny Root6dceb882012-04-12 14:23:49 -07006400 return resourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07006401 }
6402
6403 @Override
6404 String getNativeLibraryPath() {
6405 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006406 }
6407
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006408 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006409 if (status != PackageManager.INSTALL_SUCCEEDED) {
6410 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006411 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006412 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006413 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006414 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07006415 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
6416 Process.SYSTEM_UID);
6417 if (newCachePath != null) {
6418 setCachePath(newCachePath);
6419 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006420 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6421 }
6422 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006423 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006424 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006425 }
6426
6427 boolean doRename(int status, final String pkgName,
6428 String oldCodePath) {
6429 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006430 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006431 if (PackageHelper.isContainerMounted(cid)) {
6432 // Unmount the container
6433 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006434 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006435 return false;
6436 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006437 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006438 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07006439 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
6440 " which might be stale. Will try to clean up.");
6441 // Clean up the stale container and proceed to recreate.
6442 if (!PackageHelper.destroySdDir(newCacheId)) {
6443 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
6444 return false;
6445 }
6446 // Successfully cleaned up stale container. Try to rename again.
6447 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
6448 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
6449 + " inspite of cleaning it up.");
6450 return false;
6451 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006452 }
6453 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006454 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006455 newCachePath = PackageHelper.mountSdDir(newCacheId,
6456 getEncryptKey(), Process.SYSTEM_UID);
6457 } else {
6458 newCachePath = PackageHelper.getSdDir(newCacheId);
6459 }
6460 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006461 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006462 return false;
6463 }
6464 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07006465 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006466 " at new path: " + newCachePath);
6467 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07006468 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08006469 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006470 }
6471
Kenny Root85387d72010-08-26 10:13:11 -07006472 private void setCachePath(String newCachePath) {
6473 File cachePath = new File(newCachePath);
6474 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
6475 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
Kenny Root6dceb882012-04-12 14:23:49 -07006476
6477 if (isFwdLocked()) {
6478 resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
6479 } else {
6480 resourcePath = packagePath;
6481 }
Kenny Root85387d72010-08-26 10:13:11 -07006482 }
6483
Kenny Root6dceb882012-04-12 14:23:49 -07006484 int doPostInstall(int status, int uid) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006485 if (status != PackageManager.INSTALL_SUCCEEDED) {
6486 cleanUp();
6487 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07006488 final int groupOwner;
6489 final String protectedFile;
6490 if (isFwdLocked()) {
6491 groupOwner = uid;
6492 protectedFile = RES_FILE_NAME;
6493 } else {
6494 groupOwner = -1;
6495 protectedFile = null;
6496 }
6497
Kenny Root6dceb882012-04-12 14:23:49 -07006498 if (uid < Process.FIRST_APPLICATION_UID
Kenny Rootbf023582012-05-02 16:56:15 -07006499 || !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Kenny Root6dceb882012-04-12 14:23:49 -07006500 Slog.e(TAG, "Failed to finalize " + cid);
6501 PackageHelper.destroySdDir(cid);
6502 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6503 }
6504
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006505 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006506 if (!mounted) {
Kenny Root6dceb882012-04-12 14:23:49 -07006507 PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006508 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006509 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006510 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006511 }
6512
6513 private void cleanUp() {
Kenny Root6dceb882012-04-12 14:23:49 -07006514 if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
6515
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006516 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006517 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006518 }
6519
6520 void cleanUpResourcesLI() {
6521 String sourceFile = getCodePath();
6522 // Remove dex file
Jeff Brown5d6d90f2011-07-11 13:04:53 -07006523 int retCode = mInstaller.rmdex(sourceFile);
6524 if (retCode < 0) {
6525 Slog.w(TAG, "Couldn't remove dex file for package: "
6526 + " at location "
6527 + sourceFile.toString() + ", retcode=" + retCode);
6528 // we don't consider this to be a failure of the core package deletion
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006529 }
6530 cleanUp();
6531 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006532
6533 boolean matchContainer(String app) {
6534 if (cid.startsWith(app)) {
6535 return true;
6536 }
6537 return false;
6538 }
6539
6540 String getPackageName() {
6541 int idx = cid.lastIndexOf("-");
6542 if (idx == -1) {
6543 return cid;
6544 }
6545 return cid.substring(0, idx);
6546 }
6547
6548 boolean doPostDeleteLI(boolean delete) {
6549 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006550 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006551 if (mounted) {
6552 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08006553 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006554 }
6555 if (ret && delete) {
6556 cleanUpResourcesLI();
6557 }
6558 return ret;
6559 }
Kenny Rootbf023582012-05-02 16:56:15 -07006560
6561 @Override
6562 int doPreCopy() {
6563 if (isFwdLocked()) {
6564 if (!PackageHelper.fixSdPermissions(cid,
6565 getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
6566 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6567 }
6568 }
6569
6570 return PackageManager.INSTALL_SUCCEEDED;
6571 }
6572
6573 @Override
6574 int doPostCopy(int uid) {
6575 if (isFwdLocked()) {
6576 PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME);
6577 if (uid < Process.FIRST_APPLICATION_UID
6578 || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) {
6579 Slog.e(TAG, "Failed to finalize " + cid);
6580 PackageHelper.destroySdDir(cid);
6581 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
6582 }
6583 }
6584
6585 return PackageManager.INSTALL_SUCCEEDED;
6586 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006587 };
6588
6589 // Utility method used to create code paths based on package name and available index.
6590 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
6591 String idxStr = "";
6592 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006593 // Fall back to default value of idx=1 if prefix is not
6594 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006595 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006596 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006597 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00006598 if (subStr.endsWith(suffix)) {
6599 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006600 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006601 // If oldCodePath already contains prefix find out the
6602 // ending index to either increment or decrement.
6603 int sidx = subStr.lastIndexOf(prefix);
6604 if (sidx != -1) {
6605 subStr = subStr.substring(sidx + prefix.length());
6606 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006607 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
6608 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006609 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006610 try {
6611 idx = Integer.parseInt(subStr);
6612 if (idx <= 1) {
6613 idx++;
6614 } else {
6615 idx--;
6616 }
6617 } catch(NumberFormatException e) {
6618 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006619 }
6620 }
6621 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006622 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006623 return prefix + idxStr;
6624 }
6625
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006626 // Utility method used to ignore ADD/REMOVE events
6627 // by directory observer.
6628 private static boolean ignoreCodePath(String fullPathStr) {
6629 String apkName = getApkName(fullPathStr);
6630 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
6631 if (idx != -1 && ((idx+1) < apkName.length())) {
6632 // Make sure the package ends with a numeral
6633 String version = apkName.substring(idx+1);
6634 try {
6635 Integer.parseInt(version);
6636 return true;
6637 } catch (NumberFormatException e) {}
6638 }
6639 return false;
6640 }
6641
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006642 // Utility method that returns the relative package path with respect
6643 // to the installation directory. Like say for /data/data/com.test-1.apk
6644 // string com.test-1 is returned.
6645 static String getApkName(String codePath) {
6646 if (codePath == null) {
6647 return null;
6648 }
6649 int sidx = codePath.lastIndexOf("/");
6650 int eidx = codePath.lastIndexOf(".");
6651 if (eidx == -1) {
6652 eidx = codePath.length();
6653 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006654 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006655 return null;
6656 }
6657 return codePath.substring(sidx+1, eidx);
6658 }
6659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 class PackageInstalledInfo {
6661 String name;
6662 int uid;
6663 PackageParser.Package pkg;
6664 int returnCode;
6665 PackageRemovedInfo removedInfo;
6666 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 /*
6669 * Install a non-existing package.
6670 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006671 private void installNewPackageLI(PackageParser.Package pkg,
6672 int parseFlags,
6673 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006674 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006676 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08006677
Amith Yamasani0b285492011-04-14 17:35:23 -07006678 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 res.name = pkgName;
6680 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07006681 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
6682 // A package with the same name is already installed, though
6683 // it has been renamed to an older name. The package we
6684 // are trying to install should be installed as an update to
6685 // the existing one, but that has not been requested, so bail.
6686 Slog.w(TAG, "Attempt to re-install " + pkgName
6687 + " without first uninstalling package running as "
6688 + mSettings.mRenamedPackages.get(pkgName));
6689 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6690 return;
6691 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006692 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006694 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 + " without first uninstalling.");
6696 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
6697 return;
6698 }
6699 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006700 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006701 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
6702 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006703 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006704 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
6706 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
6707 }
6708 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006709 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02006710 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006711 res);
6712 // delete the partially installed application. the data directory will have to be
6713 // restored if it was already existing
6714 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
6715 // remove package from internal structures. Note that we want deletePackageX to
6716 // delete the package data and cache directories that it created in
6717 // scanPackageLocked, unless those directories existed before we even tried to
6718 // install.
6719 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006720 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006721 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006722 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 }
6724 }
6725 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006726
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006727 private void replacePackageLI(PackageParser.Package pkg,
6728 int parseFlags,
6729 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006730 String installerPackageName, PackageInstalledInfo res) {
6731
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006732 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006733 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 // First find the old package info and check signatures
6735 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006736 oldPackage = mPackages.get(pkgName);
Kenny Root447106f2011-03-23 11:00:15 -07006737 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07006738 != PackageManager.SIGNATURE_MATCH) {
Kenny Root8c11f1d2012-04-14 12:10:38 -07006739 Slog.w(TAG, "New package has a different signature: " + pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
6741 return;
6742 }
6743 }
Kenny Root85387d72010-08-26 10:13:11 -07006744 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006745 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006746 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006748 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 }
6750 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006753 PackageParser.Package pkg,
6754 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006755 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006756 PackageParser.Package newPackage = null;
6757 String pkgName = deletedPackage.packageName;
6758 boolean deletedPkg = true;
6759 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006760
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006761 long origUpdateTime;
6762 if (pkg.mExtras != null) {
6763 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
6764 } else {
6765 origUpdateTime = 0;
6766 }
6767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006769 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006770 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006771 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
6773 deletedPkg = false;
6774 } else {
6775 // Successfully deleted the old package. Now proceed with re-installation
6776 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006777 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
6778 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006780 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
6782 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08006783 }
6784 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006785 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02006786 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 res);
6788 updatedSettings = true;
6789 }
6790 }
6791
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006792 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006793 // remove package from internal structures. Note that we want deletePackageX to
6794 // delete the package data and cache directories that it created in
6795 // scanPackageLocked, unless those directories existed before we even tried to
6796 // install.
6797 if(updatedSettings) {
6798 deletePackageLI(
6799 pkgName, true,
6800 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006801 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 }
6803 // Since we failed to install the new package we need to restore the old
6804 // package that we deleted.
6805 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006806 File restoreFile = new File(deletedPackage.mPath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006807 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006808 boolean oldOnSd = isExternal(deletedPackage);
6809 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
6810 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
6811 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006812 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
6813 | SCAN_UPDATE_TIME;
6814 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
6815 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006816 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
6817 return;
6818 }
6819 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07006820 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006821 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006822 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08006823 UPDATE_PERMISSIONS_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07006824 // can downgrade to reader
6825 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006826 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006827 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006828 }
6829 }
6830 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006832 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006833 PackageParser.Package pkg,
6834 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02006835 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 PackageParser.Package newPackage = null;
6837 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006838 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 PackageParser.PARSE_IS_SYSTEM;
6840 String packageName = deletedPackage.packageName;
6841 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
6842 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006843 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006844 return;
6845 }
6846 PackageParser.Package oldPkg;
6847 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07006848 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 synchronized (mPackages) {
6850 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006851 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
6853 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006854 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 return;
6856 }
6857 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006858
6859 killApplication(packageName, oldPkg.applicationInfo.uid);
6860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006861 res.removedInfo.uid = oldPkg.applicationInfo.uid;
6862 res.removedInfo.removedPackage = packageName;
6863 // Remove existing system package
6864 removePackageLI(oldPkg, true);
Kenny Root447106f2011-03-23 11:00:15 -07006865 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08006866 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006867 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006868 // We didn't need to disable the .apk as a current system package,
6869 // which means we are replacing another update that is already
6870 // installed. We need to make sure to delete the older one's .apk.
Kenny Root6dceb882012-04-12 14:23:49 -07006871 res.removedInfo.args = createInstallArgs(0,
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006872 deletedPackage.applicationInfo.sourceDir,
6873 deletedPackage.applicationInfo.publicSourceDir,
6874 deletedPackage.applicationInfo.nativeLibraryDir);
6875 } else {
6876 res.removedInfo.args = null;
6877 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08006878 }
6879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006880 // Successfully disabled the old package. Now proceed with re-installation
6881 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
6882 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006883 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006885 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006886 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
6887 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
6888 }
6889 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006890 if (newPackage.mExtras != null) {
6891 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
6892 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
6893 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
6894 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006895 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006896 updatedSettings = true;
6897 }
6898
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006899 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 // Re installation failed. Restore old information
6901 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07006902 if (newPackage != null) {
6903 removePackageLI(newPackage, true);
6904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006906 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 // Restore the old system information in Settings
6908 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006909 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07006910 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02006911 mSettings.setInstallerPackageName(packageName,
6912 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 }
Kenny Root447106f2011-03-23 11:00:15 -07006914 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 }
6916 }
6917 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006918
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006919 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006920 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006921 int retCode;
6922 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
6923 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
6924 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07006925 if (mNoDexOpt) {
6926 /*
6927 * If we're in an engineering build, programs are lazily run
6928 * through dexopt. If the .dex file doesn't exist yet, it
6929 * will be created when the program is run next.
6930 */
6931 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
6932 } else {
6933 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
6934 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6935 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006936 }
6937 }
6938 return PackageManager.INSTALL_SUCCEEDED;
6939 }
6940
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006941 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02006942 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006943 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006944 synchronized (mPackages) {
6945 //write settings. the installStatus will be incomplete at this stage.
6946 //note that the new package setting would have already been
6947 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07006948 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07006949 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950 }
6951
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006952 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006953 != PackageManager.INSTALL_SUCCEEDED) {
6954 // Discontinue if moving dex files failed.
6955 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006956 }
Kenny Root6dceb882012-04-12 14:23:49 -07006957
6958 Log.d(TAG, "New package installed in " + newPackage.mPath);
6959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006960 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006961 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborne639da72012-02-21 15:11:13 -08006962 UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
6963 ? UPDATE_PERMISSIONS_ALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006964 res.name = pkgName;
6965 res.uid = newPackage.applicationInfo.uid;
6966 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07006967 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02006968 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6970 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07006971 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006972 }
6973 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006974
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006975 private void installPackageLI(InstallArgs args,
6976 boolean newInstall, PackageInstalledInfo res) {
6977 int pFlags = args.flags;
6978 String installerPackageName = args.installerPackageName;
6979 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006980 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006981 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006982 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006983 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006984 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006985 // Result object to be returned
6986 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6987
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006988 // Retrieve PackageSettings and parse package
Kenny Root6dceb882012-04-12 14:23:49 -07006989 int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
6990 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
6991 | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006992 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
6993 pp.setSeparateProcesses(mSeparateProcesses);
6994 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
6995 null, mMetrics, parseFlags);
6996 if (pkg == null) {
6997 res.returnCode = pp.getParseError();
6998 return;
6999 }
7000 String pkgName = res.name = pkg.packageName;
7001 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
7002 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
7003 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
7004 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007005 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007006 }
7007 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
7008 res.returnCode = pp.getParseError();
7009 return;
7010 }
Kenny Root5ab21572011-07-27 11:11:19 -07007011
7012 /* If the installer passed in a manifest digest, compare it now. */
7013 if (args.manifestDigest != null) {
7014 if (DEBUG_INSTALL) {
7015 final String parsedManifest = pkg.manifestDigest == null ? "null"
7016 : pkg.manifestDigest.toString();
7017 Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
7018 + parsedManifest);
7019 }
7020
7021 if (!args.manifestDigest.equals(pkg.manifestDigest)) {
7022 res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
7023 return;
7024 }
7025 } else if (DEBUG_INSTALL) {
7026 final String parsedManifest = pkg.manifestDigest == null
7027 ? "null" : pkg.manifestDigest.toString();
7028 Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
7029 }
7030
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007031 // Get rid of all references to package scan path via parser.
7032 pp = null;
7033 String oldCodePath = null;
7034 boolean systemApp = false;
7035 synchronized (mPackages) {
7036 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007037 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
7038 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08007039 if (pkg.mOriginalPackages != null
7040 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007041 && mPackages.containsKey(oldName)) {
7042 // This package is derived from an original package,
7043 // and this device has been updating from that original
7044 // name. We must continue using the original name, so
7045 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08007046 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007047 pkgName = pkg.packageName;
7048 replace = true;
7049 } else if (mPackages.containsKey(pkgName)) {
7050 // This package, under its official name, already exists
7051 // on the device; we should replace it.
7052 replace = true;
7053 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007054 }
7055 PackageSetting ps = mSettings.mPackages.get(pkgName);
7056 if (ps != null) {
7057 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
7058 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
7059 systemApp = (ps.pkg.applicationInfo.flags &
7060 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07007061 }
7062 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007063 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007064
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007065 if (systemApp && onSd) {
7066 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007067 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007068 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
7069 return;
7070 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08007071
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007072 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
7073 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
7074 return;
7075 }
7076 // Set application objects path explicitly after the rename
7077 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07007078 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007079 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007080 replacePackageLI(pkg, parseFlags, scanMode,
7081 installerPackageName, res);
7082 } else {
7083 installNewPackageLI(pkg, parseFlags, scanMode,
7084 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 }
7086 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007087
Kenny Root85387d72010-08-26 10:13:11 -07007088 private static boolean isForwardLocked(PackageParser.Package pkg) {
7089 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007090 }
7091
Kenny Root85387d72010-08-26 10:13:11 -07007092 private static boolean isExternal(PackageParser.Package pkg) {
7093 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7094 }
7095
Kenny Root6dceb882012-04-12 14:23:49 -07007096 private static boolean isExternal(PackageSetting ps) {
7097 return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
7098 }
7099
Kenny Root85387d72010-08-26 10:13:11 -07007100 private static boolean isSystemApp(PackageParser.Package pkg) {
7101 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7102 }
7103
Kenny Root502e9a42011-01-10 13:48:15 -08007104 private static boolean isSystemApp(ApplicationInfo info) {
7105 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
7106 }
7107
Kenny Root85387d72010-08-26 10:13:11 -07007108 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
7109 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07007110 }
7111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007112 private void deleteTempPackageFiles() {
7113 FilenameFilter filter = new FilenameFilter() {
7114 public boolean accept(File dir, String name) {
7115 return name.startsWith("vmdl") && name.endsWith(".tmp");
7116 }
7117 };
7118 String tmpFilesList[] = mAppInstallDir.list(filter);
7119 if(tmpFilesList == null) {
7120 return;
7121 }
7122 for(int i = 0; i < tmpFilesList.length; i++) {
7123 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
7124 tmpFile.delete();
7125 }
7126 }
7127
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007128 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007129 File tmpPackageFile;
7130 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007131 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007133 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 return null;
7135 }
7136 try {
7137 FileUtils.setPermissions(
7138 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
7139 -1, -1);
7140 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007141 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 return null;
7143 }
7144 return tmpPackageFile;
7145 }
7146
7147 public void deletePackage(final String packageName,
7148 final IPackageDeleteObserver observer,
7149 final int flags) {
7150 mContext.enforceCallingOrSelfPermission(
7151 android.Manifest.permission.DELETE_PACKAGES, null);
7152 // Queue up an async operation since the package deletion may take a little while.
7153 mHandler.post(new Runnable() {
7154 public void run() {
7155 mHandler.removeCallbacks(this);
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007156 final int returnCode = deletePackageX(packageName, true, true, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 if (observer != null) {
7158 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007159 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007160 } catch (RemoteException e) {
7161 Log.i(TAG, "Observer no longer exists.");
7162 } //end catch
7163 } //end if
7164 } //end run
7165 });
7166 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 /**
7169 * This method is an internal method that could be get invoked either
7170 * to delete an installed package or to clean up a failed installation.
7171 * After deleting an installed package, a broadcast is sent to notify any
7172 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007173 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 * installation wouldn't have sent the initial broadcast either
7175 * The key steps in deleting a package are
7176 * deleting the package information in internal structures like mPackages,
7177 * deleting the packages base directories through installd
7178 * updating mSettings to reflect current status
7179 * persisting settings for later use
7180 * sending a broadcast if necessary
7181 */
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007182 private int deletePackageX(String packageName, boolean sendBroadCast,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007183 boolean deleteCodeAndResources, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007184 final PackageRemovedInfo info = new PackageRemovedInfo();
7185 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007187 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
7188 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
7189 try {
7190 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007191 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007192 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08007193 }
7194 } catch (RemoteException e) {
7195 }
7196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007198 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007199 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007200 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007201
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007202 if (res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07007203 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007204 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07007205
7206 // If the removed package was a system update, the old system packaged
7207 // was re-enabled; we need to broadcast this information
7208 if (systemUpdate) {
7209 Bundle extras = new Bundle(1);
7210 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
7211 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7212
Dianne Hackborne7f97212011-02-24 14:40:20 -08007213 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007214 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007215 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
Amith Yamasani13593602012-03-22 16:16:17 -07007216 extras, null, null, UserId.USER_ALL);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007217 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
Amith Yamasani13593602012-03-22 16:16:17 -07007218 null, packageName, null, UserId.USER_ALL);
Romain Guy96f43572009-03-24 20:27:49 -07007219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007221 // Force a gc here.
7222 Runtime.getRuntime().gc();
7223 // Delete the resources here after sending the broadcast to let
7224 // other processes clean up before deleting resources.
7225 if (info.args != null) {
7226 synchronized (mInstallLock) {
7227 info.args.doPostDeleteLI(deleteCodeAndResources);
7228 }
7229 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08007230
7231 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 }
7233
7234 static class PackageRemovedInfo {
7235 String removedPackage;
7236 int uid = -1;
7237 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07007238 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007239 // Clean up resources deleted packages.
7240 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07007241
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07007242 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007243 Bundle extras = new Bundle(1);
7244 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
7245 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
7246 if (replacing) {
7247 extras.putBoolean(Intent.EXTRA_REPLACING, true);
7248 }
7249 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08007250 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007251 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007252 if (fullRemove && !replacing) {
7253 sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED, removedPackage,
Amith Yamasani13593602012-03-22 16:16:17 -07007254 extras, null, null, UserId.USER_ALL);
Dianne Hackbornf9abb402011-08-10 15:00:59 -07007255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 }
7257 if (removedUid >= 0) {
Amith Yamasani13593602012-03-22 16:16:17 -07007258 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null,
7259 UserId.getUserId(removedUid));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007260 }
7261 }
7262 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 /*
7265 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
7266 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007267 * 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 -08007268 * delete a partially installed application.
7269 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007270 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007271 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007273 if (outInfo != null) {
7274 outInfo.removedPackage = packageName;
7275 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07007276 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007277 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07007278 final PackageSetting deletedPs;
7279 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007280 synchronized (mPackages) {
7281 deletedPs = mSettings.mPackages.get(packageName);
7282 }
7283 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007284 int retCode = mInstaller.remove(packageName, 0);
7285 if (retCode < 0) {
7286 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
7287 + packageName + ", retcode=" + retCode);
7288 // we don't consider this to be a failure of the core package deletion
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007289 } else {
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007290 // TODO: Kill the processes first
Amith Yamasani13593602012-03-22 16:16:17 -07007291 sUserManager.removePackageForAllUsers(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07007293 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 }
Kenny Root447106f2011-03-23 11:00:15 -07007295 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007297 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007298 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
7299 if (outInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07007300 outInfo.removedUid = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007301 }
7302 if (deletedPs != null) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007303 updatePermissionsLPw(deletedPs.name, null, 0);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007304 if (deletedPs.sharedUser != null) {
7305 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07007306 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007307 }
7308 }
Dianne Hackborn04505102012-02-29 12:34:04 -08007309 clearPackagePreferredActivitiesLPw(deletedPs.name);
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007310 }
7311 }
Kenny Root447106f2011-03-23 11:00:15 -07007312 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007313 if (writeSettings) {
7314 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07007315 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 }
7318 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 /*
7321 * Tries to delete system package.
7322 */
7323 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007324 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007325 ApplicationInfo applicationInfo = p.applicationInfo;
7326 //applicable for non-partially installed applications only
7327 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007328 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 return false;
7330 }
7331 PackageSetting ps = null;
7332 // Confirm if the system package has been updated
7333 // An updated system app can be deleted. This will also have to restore
7334 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07007335 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007337 ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007338 }
7339 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007340 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 return false;
7342 } else {
7343 Log.i(TAG, "Deleting system pkg from data partition");
7344 }
7345 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07007346 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007347 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007348 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007349 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007350 } else {
7351 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07007352 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007353 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007354 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007355 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 if (!ret) {
7357 return false;
7358 }
Kenny Root447106f2011-03-23 11:00:15 -07007359 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 synchronized (mPackages) {
7361 // Reinstate the old system package
Kenny Root447106f2011-03-23 11:00:15 -07007362 mSettings.enableSystemPackageLPw(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07007363 // Remove any native libraries from the upgraded package.
7364 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007365 }
7366 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007367 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007369 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007372 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 return false;
7374 }
Kenny Root447106f2011-03-23 11:00:15 -07007375 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 synchronized (mPackages) {
Dianne Hackborne639da72012-02-21 15:11:13 -08007377 updatePermissionsLPw(newPkg.packageName, newPkg,
7378 UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
Kenny Root447106f2011-03-23 11:00:15 -07007379 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007380 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07007381 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007383 }
7384 return true;
7385 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007387 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007388 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7389 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 ApplicationInfo applicationInfo = p.applicationInfo;
7391 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007392 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 return false;
7394 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007395 if (outInfo != null) {
7396 outInfo.uid = applicationInfo.uid;
7397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398
7399 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007400 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401
7402 // Delete application code and resources
7403 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007404 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07007405 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
7406 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
7407 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
7408 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 }
7410 return true;
7411 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 /*
7414 * This method handles package deletion in general
7415 */
7416 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007417 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
7418 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007420 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 return false;
7422 }
7423 PackageParser.Package p;
7424 boolean dataOnly = false;
7425 synchronized (mPackages) {
7426 p = mPackages.get(packageName);
7427 if (p == null) {
7428 //this retrieves partially installed apps
7429 dataOnly = true;
7430 PackageSetting ps = mSettings.mPackages.get(packageName);
7431 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007432 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 return false;
7434 }
7435 p = ps.pkg;
7436 }
7437 }
7438 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007439 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 return false;
7441 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 if (dataOnly) {
7444 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007445 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 return true;
7447 }
7448 // At this point the package should have ApplicationInfo associated with it
7449 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007450 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451 return false;
7452 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007453 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07007454 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 Log.i(TAG, "Removing system package:"+p.packageName);
7456 // When an updated system application is deleted we delete the existing resources as well and
7457 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007458 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007459 } else {
7460 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007461 // Kill application pre-emptively especially for apps on sd.
7462 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007463 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
7464 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007466 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007468
Amith Yamasani483f3b02012-03-13 16:08:00 -07007469 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007470 public void clearApplicationUserData(final String packageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07007471 final IPackageDataObserver observer, final int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007472 mContext.enforceCallingOrSelfPermission(
7473 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
Amith Yamasani483f3b02012-03-13 16:08:00 -07007474 checkValidCaller(Binder.getCallingUid(), userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 // Queue up an async operation since the package deletion may take a little while.
7476 mHandler.post(new Runnable() {
7477 public void run() {
7478 mHandler.removeCallbacks(this);
7479 final boolean succeeded;
7480 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007481 succeeded = clearApplicationUserDataLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007482 }
7483 if (succeeded) {
7484 // invoke DeviceStorageMonitor's update method to clear any notifications
7485 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
7486 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
7487 if (dsm != null) {
7488 dsm.updateMemory();
7489 }
7490 }
7491 if(observer != null) {
7492 try {
7493 observer.onRemoveCompleted(packageName, succeeded);
7494 } catch (RemoteException e) {
7495 Log.i(TAG, "Observer no longer exists.");
7496 }
7497 } //end if observer
7498 } //end run
7499 });
7500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007501
Amith Yamasani483f3b02012-03-13 16:08:00 -07007502 private boolean clearApplicationUserDataLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007503 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007504 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 return false;
7506 }
7507 PackageParser.Package p;
7508 boolean dataOnly = false;
7509 synchronized (mPackages) {
7510 p = mPackages.get(packageName);
7511 if(p == null) {
7512 dataOnly = true;
7513 PackageSetting ps = mSettings.mPackages.get(packageName);
7514 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007515 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007516 return false;
7517 }
7518 p = ps.pkg;
7519 }
7520 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08007521
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08007522 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 //need to check this only for fully installed applications
7524 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007525 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007526 return false;
7527 }
7528 final ApplicationInfo applicationInfo = p.applicationInfo;
7529 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007530 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007531 return false;
7532 }
7533 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007534 int retCode = mInstaller.clearUserData(packageName, userId);
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007535 if (retCode < 0) {
7536 Slog.w(TAG, "Couldn't remove cache files for package: "
7537 + packageName);
7538 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007539 }
7540 return true;
7541 }
7542
7543 public void deleteApplicationCacheFiles(final String packageName,
7544 final IPackageDataObserver observer) {
7545 mContext.enforceCallingOrSelfPermission(
7546 android.Manifest.permission.DELETE_CACHE_FILES, null);
7547 // Queue up an async operation since the package deletion may take a little while.
Amith Yamasani483f3b02012-03-13 16:08:00 -07007548 final int userId = UserId.getCallingUserId();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 mHandler.post(new Runnable() {
7550 public void run() {
7551 mHandler.removeCallbacks(this);
7552 final boolean succeded;
7553 synchronized (mInstallLock) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07007554 succeded = deleteApplicationCacheFilesLI(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007555 }
7556 if(observer != null) {
7557 try {
7558 observer.onRemoveCompleted(packageName, succeded);
7559 } catch (RemoteException e) {
7560 Log.i(TAG, "Observer no longer exists.");
7561 }
7562 } //end if observer
7563 } //end run
7564 });
7565 }
7566
Amith Yamasani483f3b02012-03-13 16:08:00 -07007567 private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007569 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007570 return false;
7571 }
7572 PackageParser.Package p;
7573 synchronized (mPackages) {
7574 p = mPackages.get(packageName);
7575 }
7576 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007577 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 return false;
7579 }
7580 final ApplicationInfo applicationInfo = p.applicationInfo;
7581 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007582 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 return false;
7584 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007585 // TODO: Pass userId to deleteCacheFiles
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007586 int retCode = mInstaller.deleteCacheFiles(packageName);
7587 if (retCode < 0) {
7588 Slog.w(TAG, "Couldn't remove cache files for package: "
7589 + packageName);
7590 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 }
7592 return true;
7593 }
7594
7595 public void getPackageSizeInfo(final String packageName,
7596 final IPackageStatsObserver observer) {
7597 mContext.enforceCallingOrSelfPermission(
7598 android.Manifest.permission.GET_PACKAGE_SIZE, null);
7599 // Queue up an async operation since the package deletion may take a little while.
7600 mHandler.post(new Runnable() {
7601 public void run() {
7602 mHandler.removeCallbacks(this);
Kenny Root366949c2011-01-14 17:18:14 -08007603 PackageStats stats = new PackageStats(packageName);
7604
7605 final boolean success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 synchronized (mInstallLock) {
Kenny Root366949c2011-01-14 17:18:14 -08007607 success = getPackageSizeInfoLI(packageName, stats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 }
Kenny Root366949c2011-01-14 17:18:14 -08007609
7610 Message msg = mHandler.obtainMessage(INIT_COPY);
7611 msg.obj = new MeasureParams(stats, success, observer);
7612 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 } //end run
7614 });
7615 }
7616
7617 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
7618 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007619 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007620 return false;
7621 }
7622 PackageParser.Package p;
7623 boolean dataOnly = false;
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007624 String asecPath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 synchronized (mPackages) {
7626 p = mPackages.get(packageName);
7627 if(p == null) {
7628 dataOnly = true;
7629 PackageSetting ps = mSettings.mPackages.get(packageName);
7630 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007631 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 return false;
7633 }
7634 p = ps.pkg;
7635 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007636 if (p != null && isExternal(p)) {
7637 String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
7638 if (secureContainerId != null) {
7639 asecPath = PackageHelper.getSdFilesystem(secureContainerId);
7640 }
7641 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007642 }
7643 String publicSrcDir = null;
7644 if(!dataOnly) {
7645 final ApplicationInfo applicationInfo = p.applicationInfo;
7646 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007647 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 return false;
7649 }
Dianne Hackborn292f8bc2011-06-27 16:27:41 -07007650 if (isForwardLocked(p)) {
7651 publicSrcDir = applicationInfo.publicSourceDir;
7652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 }
Jeff Brown5d6d90f2011-07-11 13:04:53 -07007654 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
7655 asecPath, pStats);
7656 if (res < 0) {
7657 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007658 }
7659 return true;
7660 }
7661
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07007664 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 }
7666
7667 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07007668 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007669 }
7670
7671 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007672 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 }
7674
Kenny Root447106f2011-03-23 11:00:15 -07007675 private int getUidTargetSdkVersionLockedLPr(int uid) {
7676 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007677 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07007678 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007679 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07007680 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007681 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07007682 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007683 if (ps.pkg != null) {
7684 int v = ps.pkg.applicationInfo.targetSdkVersion;
7685 if (v < vers) vers = v;
7686 }
7687 }
7688 return vers;
7689 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07007690 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007691 if (ps.pkg != null) {
7692 return ps.pkg.applicationInfo.targetSdkVersion;
7693 }
7694 }
7695 return Build.VERSION_CODES.CUR_DEVELOPMENT;
7696 }
7697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 public void addPreferredActivity(IntentFilter filter, int match,
7699 ComponentName[] set, ComponentName activity) {
Kenny Root447106f2011-03-23 11:00:15 -07007700 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007702 if (mContext.checkCallingOrSelfPermission(
7703 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
7704 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07007705 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007706 < Build.VERSION_CODES.FROYO) {
7707 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
7708 + Binder.getCallingUid());
7709 return;
7710 }
7711 mContext.enforceCallingOrSelfPermission(
7712 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
7713 }
7714
7715 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007716 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
7717 mSettings.mPreferredActivities.addFilter(
7718 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007719 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 }
7721 }
7722
Satish Sampath8dbe6122009-06-02 23:35:54 +01007723 public void replacePreferredActivity(IntentFilter filter, int match,
7724 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01007725 if (filter.countActions() != 1) {
7726 throw new IllegalArgumentException(
7727 "replacePreferredActivity expects filter to have only 1 action.");
7728 }
7729 if (filter.countCategories() != 1) {
7730 throw new IllegalArgumentException(
7731 "replacePreferredActivity expects filter to have only 1 category.");
7732 }
7733 if (filter.countDataAuthorities() != 0
7734 || filter.countDataPaths() != 0
7735 || filter.countDataSchemes() != 0
7736 || filter.countDataTypes() != 0) {
7737 throw new IllegalArgumentException(
7738 "replacePreferredActivity expects filter to have no data authorities, " +
7739 "paths, schemes or types.");
7740 }
7741 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007742 if (mContext.checkCallingOrSelfPermission(
7743 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
7744 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07007745 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007746 < Build.VERSION_CODES.FROYO) {
7747 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
7748 + Binder.getCallingUid());
7749 return;
7750 }
7751 mContext.enforceCallingOrSelfPermission(
7752 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
7753 }
7754
Dianne Hackborn04505102012-02-29 12:34:04 -08007755 ArrayList<PreferredActivity> removed = null;
Satish Sampath8dbe6122009-06-02 23:35:54 +01007756 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
7757 String action = filter.getAction(0);
7758 String category = filter.getCategory(0);
7759 while (it.hasNext()) {
7760 PreferredActivity pa = it.next();
7761 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08007762 if (removed == null) {
7763 removed = new ArrayList<PreferredActivity>();
7764 }
7765 removed.add(pa);
7766 Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
Satish Sampath8dbe6122009-06-02 23:35:54 +01007767 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
7768 }
7769 }
Dianne Hackborn04505102012-02-29 12:34:04 -08007770 if (removed != null) {
7771 for (int i=0; i<removed.size(); i++) {
7772 PreferredActivity pa = removed.get(i);
7773 mSettings.mPreferredActivities.removeFilter(pa);
7774 }
7775 }
Satish Sampath8dbe6122009-06-02 23:35:54 +01007776 addPreferredActivity(filter, match, set, activity);
7777 }
7778 }
7779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07007781 final int uid = Binder.getCallingUid();
7782 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08007784 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007785 if (pkg == null || pkg.applicationInfo.uid != uid) {
7786 if (mContext.checkCallingOrSelfPermission(
7787 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
7788 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07007789 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007790 < Build.VERSION_CODES.FROYO) {
7791 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
7792 + Binder.getCallingUid());
7793 return;
7794 }
7795 mContext.enforceCallingOrSelfPermission(
7796 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
7797 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08007798 }
7799
Kenny Root447106f2011-03-23 11:00:15 -07007800 if (clearPackagePreferredActivitiesLPw(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007801 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 }
7803 }
7804 }
7805
Kenny Root447106f2011-03-23 11:00:15 -07007806 boolean clearPackagePreferredActivitiesLPw(String packageName) {
Dianne Hackborn04505102012-02-29 12:34:04 -08007807 ArrayList<PreferredActivity> removed = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007808 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
7809 while (it.hasNext()) {
7810 PreferredActivity pa = it.next();
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08007811 if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
Dianne Hackborn04505102012-02-29 12:34:04 -08007812 if (removed == null) {
7813 removed = new ArrayList<PreferredActivity>();
7814 }
7815 removed.add(pa);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 }
7817 }
Dianne Hackborn04505102012-02-29 12:34:04 -08007818 if (removed != null) {
7819 for (int i=0; i<removed.size(); i++) {
7820 PreferredActivity pa = removed.get(i);
7821 mSettings.mPreferredActivities.removeFilter(pa);
7822 }
7823 return true;
7824 }
7825 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 }
7827
7828 public int getPreferredActivities(List<IntentFilter> outFilters,
7829 List<ComponentName> outActivities, String packageName) {
7830
7831 int num = 0;
Kenny Root447106f2011-03-23 11:00:15 -07007832 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007834 final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07007836 final PreferredActivity pa = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007837 if (packageName == null
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08007838 || pa.mPref.mComponent.getPackageName().equals(packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 if (outFilters != null) {
7840 outFilters.add(new IntentFilter(pa));
7841 }
7842 if (outActivities != null) {
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08007843 outActivities.add(pa.mPref.mComponent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007844 }
7845 }
7846 }
7847 }
7848
7849 return num;
7850 }
7851
Amith Yamasani483f3b02012-03-13 16:08:00 -07007852 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 public void setApplicationEnabledSetting(String appPackageName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07007854 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07007855 if (!sUserManager.exists(userId)) return;
Amith Yamasani483f3b02012-03-13 16:08:00 -07007856 setEnabledSetting(appPackageName, null, newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007857 }
7858
Amith Yamasani483f3b02012-03-13 16:08:00 -07007859 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007860 public void setComponentEnabledSetting(ComponentName componentName,
Amith Yamasani483f3b02012-03-13 16:08:00 -07007861 int newState, int flags, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07007862 if (!sUserManager.exists(userId)) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007863 setEnabledSetting(componentName.getPackageName(),
Amith Yamasani483f3b02012-03-13 16:08:00 -07007864 componentName.getClassName(), newState, flags, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 }
7866
7867 private void setEnabledSetting(
Amith Yamasani483f3b02012-03-13 16:08:00 -07007868 final String packageName, String className, int newState, final int flags, int userId) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007869 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
7870 || newState == COMPONENT_ENABLED_STATE_ENABLED
Dianne Hackborn0ac30312011-06-17 14:49:23 -07007871 || newState == COMPONENT_ENABLED_STATE_DISABLED
7872 || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007873 throw new IllegalArgumentException("Invalid new component state: "
7874 + newState);
7875 }
7876 PackageSetting pkgSetting;
7877 final int uid = Binder.getCallingUid();
7878 final int permission = mContext.checkCallingPermission(
7879 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
Amith Yamasani483f3b02012-03-13 16:08:00 -07007880 checkValidCaller(uid, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007882 boolean sendNow = false;
7883 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007884 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007885 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007886 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -07007887
7888 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007890 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007892 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007894 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 }
7896 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007897 "Unknown component: " + packageName
7898 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007900 // Allow root and verify that userId is not being specified by a different user
Amith Yamasani13593602012-03-22 16:16:17 -07007901 if (!allowedByPermission && !UserId.isSameApp(uid, pkgSetting.appId)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 throw new SecurityException(
7903 "Permission Denial: attempt to change component state from pid="
7904 + Binder.getCallingPid()
Amith Yamasani13593602012-03-22 16:16:17 -07007905 + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007907 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 // We're dealing with an application/package level state change
Amith Yamasani483f3b02012-03-13 16:08:00 -07007909 if (pkgSetting.getEnabled(userId) == newState) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007910 // Nothing to do
7911 return;
7912 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007913 pkgSetting.setEnabled(newState, userId);
Amith Yamasani13593602012-03-22 16:16:17 -07007914 // pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 } else {
7916 // We're dealing with a component level state change
Dianne Hackborn65696252012-03-05 18:49:21 -08007917 // First, verify that this is a valid class name.
7918 PackageParser.Package pkg = pkgSetting.pkg;
7919 if (pkg == null || !pkg.hasComponentClassName(className)) {
7920 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
7921 throw new IllegalArgumentException("Component class " + className
7922 + " does not exist in " + packageName);
7923 } else {
7924 Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
7925 + className + " does not exist in " + packageName);
7926 }
7927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 switch (newState) {
7929 case COMPONENT_ENABLED_STATE_ENABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07007930 if (!pkgSetting.enableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007931 return;
7932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 break;
7934 case COMPONENT_ENABLED_STATE_DISABLED:
Amith Yamasani483f3b02012-03-13 16:08:00 -07007935 if (!pkgSetting.disableComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007936 return;
7937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 break;
7939 case COMPONENT_ENABLED_STATE_DEFAULT:
Amith Yamasani483f3b02012-03-13 16:08:00 -07007940 if (!pkgSetting.restoreComponentLPw(className, userId)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007941 return;
7942 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943 break;
7944 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007945 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007946 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 }
7948 }
Amith Yamasani483f3b02012-03-13 16:08:00 -07007949 mSettings.writePackageRestrictionsLPr(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07007950 packageUid = UserId.getUid(userId, pkgSetting.appId);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007951 components = mPendingBroadcasts.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07007952 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007953 if (newPackage) {
7954 components = new ArrayList<String>();
7955 }
7956 if (!components.contains(componentName)) {
7957 components.add(componentName);
7958 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007959 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
7960 sendNow = true;
7961 // Purge entry from pending broadcast list if another one exists already
7962 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007963 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007964 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007965 if (newPackage) {
7966 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007967 }
7968 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
7969 // Schedule a message
7970 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
7971 }
7972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007975 long callingId = Binder.clearCallingIdentity();
7976 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007977 if (sendNow) {
7978 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007979 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 } finally {
7982 Binder.restoreCallingIdentity(callingId);
7983 }
7984 }
7985
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007986 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007987 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08007988 if (DEBUG_INSTALL)
7989 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
7990 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007991 Bundle extras = new Bundle(4);
7992 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
7993 String nameList[] = new String[componentNames.size()];
7994 componentNames.toArray(nameList);
7995 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007996 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
7997 extras.putInt(Intent.EXTRA_UID, packageUid);
Amith Yamasani13593602012-03-22 16:16:17 -07007998 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null,
7999 UserId.getUserId(packageUid));
Dianne Hackborne7f97212011-02-24 14:40:20 -08008000 }
8001
Amith Yamasani483f3b02012-03-13 16:08:00 -07008002 public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008003 if (!sUserManager.exists(userId)) return;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008004 final int uid = Binder.getCallingUid();
8005 final int permission = mContext.checkCallingOrSelfPermission(
8006 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
8007 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Amith Yamasani483f3b02012-03-13 16:08:00 -07008008 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008009 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -08008010 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008011 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
Amith Yamasani483f3b02012-03-13 16:08:00 -07008012 uid, userId)) {
8013 scheduleWritePackageRestrictionsLocked(userId);
Dianne Hackborne7f97212011-02-24 14:40:20 -08008014 }
8015 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07008016 }
8017
Jacek Surazski65e13172009-04-28 15:26:38 +02008018 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07008019 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +02008020 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07008021 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02008022 }
8023 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008024
Amith Yamasani483f3b02012-03-13 16:08:00 -07008025 @Override
8026 public int getApplicationEnabledSetting(String packageName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008027 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008028 int uid = Binder.getCallingUid();
8029 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008030 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008032 return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 }
8034 }
8035
Amith Yamasani483f3b02012-03-13 16:08:00 -07008036 @Override
8037 public int getComponentEnabledSetting(ComponentName componentName, int userId) {
Amith Yamasani13593602012-03-22 16:16:17 -07008038 if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
Amith Yamasani483f3b02012-03-13 16:08:00 -07008039 int uid = Binder.getCallingUid();
8040 checkValidCaller(uid, userId);
Kenny Root447106f2011-03-23 11:00:15 -07008041 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008042 synchronized (mPackages) {
Amith Yamasani483f3b02012-03-13 16:08:00 -07008043 return mSettings.getComponentEnabledSettingLPr(componentName, userId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008044 }
8045 }
8046
8047 public void enterSafeMode() {
Kenny Root461ff1f2011-08-09 09:43:03 -07008048 enforceSystemOrRoot("Only the system can request entering safe mode");
8049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 if (!mSystemReady) {
8051 mSafeMode = true;
8052 }
8053 }
8054
8055 public void systemReady() {
8056 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008057
8058 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008059 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008060 mContext.getContentResolver(),
8061 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008062 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008063 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07008064 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07008065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
8067
8068 public boolean isSafeMode() {
8069 return mSafeMode;
8070 }
8071
8072 public boolean hasSystemUidErrors() {
8073 return mHasSystemUidErrors;
8074 }
8075
8076 static String arrayToString(int[] array) {
8077 StringBuffer buf = new StringBuffer(128);
8078 buf.append('[');
8079 if (array != null) {
8080 for (int i=0; i<array.length; i++) {
8081 if (i > 0) buf.append(", ");
8082 buf.append(array[i]);
8083 }
8084 }
8085 buf.append(']');
8086 return buf.toString();
8087 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008088
Kenny Root447106f2011-03-23 11:00:15 -07008089 static class DumpState {
8090 public static final int DUMP_LIBS = 1 << 0;
8091
8092 public static final int DUMP_FEATURES = 1 << 1;
8093
8094 public static final int DUMP_RESOLVERS = 1 << 2;
8095
8096 public static final int DUMP_PERMISSIONS = 1 << 3;
8097
8098 public static final int DUMP_PACKAGES = 1 << 4;
8099
8100 public static final int DUMP_SHARED_USERS = 1 << 5;
8101
8102 public static final int DUMP_MESSAGES = 1 << 6;
8103
8104 public static final int DUMP_PROVIDERS = 1 << 7;
8105
Kenny Root05ca4c92011-09-15 10:36:25 -07008106 public static final int DUMP_VERIFIERS = 1 << 8;
8107
Kenny Root447106f2011-03-23 11:00:15 -07008108 public static final int OPTION_SHOW_FILTERS = 1 << 0;
8109
8110 private int mTypes;
8111
8112 private int mOptions;
8113
8114 private boolean mTitlePrinted;
8115
8116 private SharedUserSetting mSharedUser;
8117
8118 public boolean isDumping(int type) {
8119 if (mTypes == 0) {
8120 return true;
8121 }
8122
8123 return (mTypes & type) != 0;
8124 }
8125
8126 public void setDump(int type) {
8127 mTypes |= type;
8128 }
8129
8130 public boolean isOptionEnabled(int option) {
8131 return (mOptions & option) != 0;
8132 }
8133
8134 public void setOptionEnabled(int option) {
8135 mOptions |= option;
8136 }
8137
8138 public boolean onTitlePrinted() {
8139 final boolean printed = mTitlePrinted;
8140 mTitlePrinted = true;
8141 return printed;
8142 }
8143
8144 public boolean getTitlePrinted() {
8145 return mTitlePrinted;
8146 }
8147
8148 public void setTitlePrinted(boolean enabled) {
8149 mTitlePrinted = enabled;
8150 }
8151
8152 public SharedUserSetting getSharedUser() {
8153 return mSharedUser;
8154 }
8155
8156 public void setSharedUser(SharedUserSetting user) {
8157 mSharedUser = user;
8158 }
8159 }
8160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 @Override
8162 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8163 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
8164 != PackageManager.PERMISSION_GRANTED) {
8165 pw.println("Permission Denial: can't dump ActivityManager from from pid="
8166 + Binder.getCallingPid()
8167 + ", uid=" + Binder.getCallingUid()
8168 + " without permission "
8169 + android.Manifest.permission.DUMP);
8170 return;
8171 }
8172
Kenny Root447106f2011-03-23 11:00:15 -07008173 DumpState dumpState = new DumpState();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008174
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008175 String packageName = null;
8176
8177 int opti = 0;
8178 while (opti < args.length) {
8179 String opt = args[opti];
8180 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
8181 break;
8182 }
8183 opti++;
8184 if ("-a".equals(opt)) {
8185 // Right now we only know how to print all.
8186 } else if ("-h".equals(opt)) {
8187 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008188 pw.println(" [-h] [-f] [cmd] ...");
8189 pw.println(" -f: print details of intent filters");
8190 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008191 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008192 pw.println(" l[ibraries]: list known shared libraries");
8193 pw.println(" f[ibraries]: list device features");
8194 pw.println(" r[esolvers]: dump intent resolvers");
8195 pw.println(" perm[issions]: dump permissions");
8196 pw.println(" prov[iders]: dump content providers");
8197 pw.println(" p[ackages]: dump installed packages");
8198 pw.println(" s[hared-users]: dump shared user IDs");
8199 pw.println(" m[essages]: print collected runtime messages");
Kenny Root05ca4c92011-09-15 10:36:25 -07008200 pw.println(" v[erifiers]: print package verifier info");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008201 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008202 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008203 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -07008204 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008205 } else {
8206 pw.println("Unknown argument: " + opt + "; use -h for help");
8207 }
8208 }
8209
8210 // Is the caller requesting to dump a particular piece of data?
8211 if (opti < args.length) {
8212 String cmd = args[opti];
8213 opti++;
8214 // Is this a package name?
8215 if ("android".equals(cmd) || cmd.contains(".")) {
8216 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008217 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008218 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008219 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008220 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008221 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008222 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008223 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008224 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008225 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008226 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008227 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008228 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008229 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008230 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008231 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07008232 dumpState.setDump(DumpState.DUMP_MESSAGES);
Kenny Root05ca4c92011-09-15 10:36:25 -07008233 } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
8234 dumpState.setDump(DumpState.DUMP_VERIFIERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008235 }
8236 }
Kenny Root447106f2011-03-23 11:00:15 -07008237
8238 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239 synchronized (mPackages) {
Kenny Root05ca4c92011-09-15 10:36:25 -07008240 if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
8241 if (dumpState.onTitlePrinted())
8242 pw.println(" ");
8243 pw.println("Verifiers:");
8244 pw.print(" Required: ");
8245 pw.print(mRequiredVerifierPackage);
8246 pw.print(" (uid=");
Amith Yamasani483f3b02012-03-13 16:08:00 -07008247 pw.print(getPackageUid(mRequiredVerifierPackage, 0));
Kenny Root05ca4c92011-09-15 10:36:25 -07008248 pw.println(")");
8249 }
8250
Kenny Root447106f2011-03-23 11:00:15 -07008251 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
8252 if (dumpState.onTitlePrinted())
8253 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008254 pw.println("Libraries:");
Kenny Root447106f2011-03-23 11:00:15 -07008255 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008256 while (it.hasNext()) {
8257 String name = it.next();
8258 pw.print(" ");
8259 pw.print(name);
8260 pw.print(" -> ");
8261 pw.println(mSharedLibraries.get(name));
8262 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008263 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008264
Kenny Root447106f2011-03-23 11:00:15 -07008265 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
8266 if (dumpState.onTitlePrinted())
8267 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008268 pw.println("Features:");
8269 Iterator<String> it = mAvailableFeatures.keySet().iterator();
8270 while (it.hasNext()) {
8271 String name = it.next();
8272 pw.print(" ");
8273 pw.println(name);
8274 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008275 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008276
Kenny Root447106f2011-03-23 11:00:15 -07008277 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
8278 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
8279 : "Activity Resolver Table:", " ", packageName,
8280 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8281 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008282 }
Kenny Root447106f2011-03-23 11:00:15 -07008283 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
8284 : "Receiver Resolver Table:", " ", packageName,
8285 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8286 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008287 }
Kenny Root447106f2011-03-23 11:00:15 -07008288 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
8289 : "Service Resolver Table:", " ", packageName,
8290 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8291 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008292 }
Kenny Root447106f2011-03-23 11:00:15 -07008293 if (mSettings.mPreferredActivities.dump(pw,
8294 dumpState.getTitlePrinted() ? "\nPreferred Activities:"
8295 : "Preferred Activities:", " ",
8296 packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
8297 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008298 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008299 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008300
Kenny Root447106f2011-03-23 11:00:15 -07008301 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
8302 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008304
Kenny Root447106f2011-03-23 11:00:15 -07008305 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
8306 boolean printedSomething = false;
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008307 for (PackageParser.Provider p : mProvidersByComponent.values()) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008308 if (packageName != null && !packageName.equals(p.info.packageName)) {
8309 continue;
8310 }
8311 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -07008312 if (dumpState.onTitlePrinted())
8313 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008314 pw.println("Registered ContentProviders:");
8315 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008316 }
Dianne Hackbornee9aef02011-11-16 13:21:46 -08008317 pw.print(" "); pw.print(p.getComponentShortName()); pw.println(":");
8318 pw.print(" "); pw.println(p.toString());
8319 }
8320 printedSomething = false;
8321 for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
8322 PackageParser.Provider p = entry.getValue();
8323 if (packageName != null && !packageName.equals(p.info.packageName)) {
8324 continue;
8325 }
8326 if (!printedSomething) {
8327 if (dumpState.onTitlePrinted())
8328 pw.println(" ");
8329 pw.println("ContentProvider Authorities:");
8330 printedSomething = true;
8331 }
8332 pw.print(" ["); pw.print(entry.getKey()); pw.println("]:");
8333 pw.print(" "); pw.println(p.toString());
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008334 }
8335 }
8336
Kenny Root447106f2011-03-23 11:00:15 -07008337 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
8338 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 }
Kenny Root447106f2011-03-23 11:00:15 -07008340
8341 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
8342 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008343 }
Kenny Root447106f2011-03-23 11:00:15 -07008344
8345 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
8346 if (dumpState.onTitlePrinted())
8347 pw.println(" ");
8348 mSettings.dumpReadMessagesLPr(pw, dumpState);
8349
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008350 pw.println(" ");
8351 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -07008352 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008353 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008354 try {
8355 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -07008356 final int avail = in.available();
8357 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008358 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07008359 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008360 } catch (FileNotFoundException e) {
8361 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008362 } finally {
8363 if (in != null) {
8364 try {
8365 in.close();
Kenny Root447106f2011-03-23 11:00:15 -07008366 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08008367 }
8368 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008369 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008371 }
8372 }
8373
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008374 // ------- apps on sdcard specific code -------
8375 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -07008376
Kenny Root305bcbf2010-09-03 07:56:38 -07008377 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -07008378
Kenny Root305bcbf2010-09-03 07:56:38 -07008379 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -07008380
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008381 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008382
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008383 private String getEncryptKey() {
8384 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07008385 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
8386 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008387 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07008388 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
8389 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008390 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008391 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008392 return null;
8393 }
8394 }
8395 return sdEncKey;
8396 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008397 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008398 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07008399 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -07008400 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -07008401 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008402 }
Rich Cannings8d578832010-09-09 15:12:40 -07008403
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008404 }
8405
Kenny Root447106f2011-03-23 11:00:15 -07008406 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -07008407 int tmpIdx = 1;
8408 String list[] = PackageHelper.getSecureContainerList();
8409 if (list != null) {
8410 for (final String name : list) {
8411 // Ignore null and non-temporary container entries
8412 if (name == null || !name.startsWith(mTempContainerPrefix)) {
8413 continue;
8414 }
8415
8416 String subStr = name.substring(mTempContainerPrefix.length());
8417 try {
8418 int cid = Integer.parseInt(subStr);
8419 if (cid >= tmpIdx) {
8420 tmpIdx = cid + 1;
8421 }
8422 } catch (NumberFormatException e) {
8423 }
8424 }
8425 }
8426 return mTempContainerPrefix + tmpIdx;
8427 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008428
Kenny Root447106f2011-03-23 11:00:15 -07008429 /*
8430 * Update media status on PackageManager.
8431 */
8432 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
8433 int callingUid = Binder.getCallingUid();
8434 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
8435 throw new SecurityException("Media status can only be updated by the system");
8436 }
8437 // reader; this apparently protects mMediaMounted, but should probably
8438 // be a different lock in that case.
8439 synchronized (mPackages) {
8440 Log.i(TAG, "Updating external media status from "
8441 + (mMediaMounted ? "mounted" : "unmounted") + " to "
8442 + (mediaStatus ? "mounted" : "unmounted"));
8443 if (DEBUG_SD_INSTALL)
8444 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
8445 + ", mMediaMounted=" + mMediaMounted);
8446 if (mediaStatus == mMediaMounted) {
8447 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
8448 : 0, -1);
8449 mHandler.sendMessage(msg);
8450 return;
8451 }
8452 mMediaMounted = mediaStatus;
8453 }
8454 // Queue up an async operation since the package installation may take a
8455 // little while.
8456 mHandler.post(new Runnable() {
8457 public void run() {
Kenny Root447106f2011-03-23 11:00:15 -07008458 updateExternalMediaStatusInner(mediaStatus, reportStatus);
8459 }
8460 });
8461 }
8462
8463 /*
8464 * Collect information of applications on external media, map them against
8465 * existing containers and update information based on current mount status.
8466 * Please note that we always have to report status if reportStatus has been
8467 * set to true especially when unloading packages.
8468 */
Kenny Root6dceb882012-04-12 14:23:49 -07008469 private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus) {
Kenny Root447106f2011-03-23 11:00:15 -07008470 // Collection of uids
8471 int uidArr[] = null;
8472 // Collection of stale containers
8473 HashSet<String> removeCids = new HashSet<String>();
8474 // Collection of packages on external media with valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07008475 HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
Kenny Root447106f2011-03-23 11:00:15 -07008476 // Get list of secure containers.
8477 final String list[] = PackageHelper.getSecureContainerList();
8478 if (list == null || list.length == 0) {
8479 Log.i(TAG, "No secure containers on sdcard");
8480 } else {
8481 // Process list of secure containers and categorize them
8482 // as active or stale based on their package internal state.
8483 int uidList[] = new int[list.length];
8484 int num = 0;
8485 // reader
8486 synchronized (mPackages) {
8487 for (String cid : list) {
Kenny Root6dceb882012-04-12 14:23:49 -07008488 AsecInstallArgs args = new AsecInstallArgs(cid);
Kenny Root447106f2011-03-23 11:00:15 -07008489 if (DEBUG_SD_INSTALL)
8490 Log.i(TAG, "Processing container " + cid);
8491 String pkgName = args.getPackageName();
8492 if (pkgName == null) {
8493 if (DEBUG_SD_INSTALL)
8494 Log.i(TAG, "Container : " + cid + " stale");
8495 removeCids.add(cid);
8496 continue;
8497 }
8498 if (DEBUG_SD_INSTALL)
8499 Log.i(TAG, "Looking for pkg : " + pkgName);
8500 PackageSetting ps = mSettings.mPackages.get(pkgName);
8501 // The package status is changed only if the code path
8502 // matches between settings and the container id.
8503 if (ps != null && ps.codePathString != null
8504 && ps.codePathString.equals(args.getCodePath())) {
8505 if (DEBUG_SD_INSTALL)
8506 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
8507 + " at code path: " + ps.codePathString);
8508 // We do have a valid package installed on sdcard
8509 processCids.put(args, ps.codePathString);
Amith Yamasani13593602012-03-22 16:16:17 -07008510 int uid = ps.appId;
Kenny Root447106f2011-03-23 11:00:15 -07008511 if (uid != -1) {
8512 uidList[num++] = uid;
8513 }
8514 } else {
8515 // Stale container on sdcard. Just delete
8516 if (DEBUG_SD_INSTALL)
8517 Log.i(TAG, "Container : " + cid + " stale");
8518 removeCids.add(cid);
8519 }
8520 }
8521 }
8522
8523 if (num > 0) {
8524 // Sort uid list
8525 Arrays.sort(uidList, 0, num);
8526 // Throw away duplicates
8527 uidArr = new int[num];
8528 uidArr[0] = uidList[0];
8529 int di = 0;
8530 for (int i = 1; i < num; i++) {
8531 if (uidList[i - 1] != uidList[i]) {
8532 uidArr[di++] = uidList[i];
8533 }
8534 }
8535 }
8536 }
8537 // Process packages with valid entries.
Kenny Root6dceb882012-04-12 14:23:49 -07008538 if (isMounted) {
Kenny Root447106f2011-03-23 11:00:15 -07008539 if (DEBUG_SD_INSTALL)
8540 Log.i(TAG, "Loading packages");
8541 loadMediaPackages(processCids, uidArr, removeCids);
8542 startCleaningPackages();
8543 } else {
8544 if (DEBUG_SD_INSTALL)
8545 Log.i(TAG, "Unloading packages");
8546 unloadMediaPackages(processCids, uidArr, reportStatus);
8547 }
8548 }
8549
8550 private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
8551 int uidArr[], IIntentReceiver finishedReceiver) {
8552 int size = pkgList.size();
8553 if (size > 0) {
8554 // Send broadcasts here
8555 Bundle extras = new Bundle();
8556 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
8557 .toArray(new String[size]));
8558 if (uidArr != null) {
8559 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
8560 }
8561 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
8562 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Amith Yamasani13593602012-03-22 16:16:17 -07008563 sendPackageBroadcast(action, null, extras, null, finishedReceiver, UserId.USER_ALL);
Kenny Root447106f2011-03-23 11:00:15 -07008564 }
8565 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008566
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07008567 /*
Kenny Root447106f2011-03-23 11:00:15 -07008568 * Look at potentially valid container ids from processCids If package
8569 * information doesn't match the one on record or package scanning fails,
8570 * the cid is added to list of removeCids. We currently don't delete stale
8571 * containers.
8572 */
Kenny Root6dceb882012-04-12 14:23:49 -07008573 private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07008574 HashSet<String> removeCids) {
8575 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07008576 Set<AsecInstallArgs> keys = processCids.keySet();
Kenny Root447106f2011-03-23 11:00:15 -07008577 boolean doGc = false;
Kenny Root6dceb882012-04-12 14:23:49 -07008578 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07008579 String codePath = processCids.get(args);
8580 if (DEBUG_SD_INSTALL)
8581 Log.i(TAG, "Loading container : " + args.cid);
8582 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8583 try {
8584 // Make sure there are no container errors first.
8585 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
8586 Slog.e(TAG, "Failed to mount cid : " + args.cid
8587 + " when installing from sdcard");
8588 continue;
8589 }
8590 // Check code path here.
8591 if (codePath == null || !codePath.equals(args.getCodePath())) {
8592 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
8593 + " does not match one in settings " + codePath);
8594 continue;
8595 }
8596 // Parse package
8597 int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8598 doGc = true;
8599 synchronized (mInstallLock) {
8600 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
8601 0, 0);
8602 // Scan the package
8603 if (pkg != null) {
8604 /*
8605 * TODO why is the lock being held? doPostInstall is
8606 * called in other places without the lock. This needs
8607 * to be straightened out.
8608 */
8609 // writer
8610 synchronized (mPackages) {
8611 retCode = PackageManager.INSTALL_SUCCEEDED;
8612 pkgList.add(pkg.packageName);
8613 // Post process args
Kenny Root6dceb882012-04-12 14:23:49 -07008614 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
8615 pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07008616 }
8617 } else {
8618 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
8619 }
8620 }
8621
8622 } finally {
8623 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
8624 // Don't destroy container here. Wait till gc clears things
8625 // up.
8626 removeCids.add(args.cid);
8627 }
8628 }
8629 }
8630 // writer
8631 synchronized (mPackages) {
8632 // If the platform SDK has changed since the last time we booted,
8633 // we need to re-grant app permission to catch any new ones that
8634 // appear. This is really a hack, and means that apps can in some
8635 // cases get permissions that the user didn't initially explicitly
8636 // allow... it would be nice to have some better way to handle
8637 // this situation.
8638 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
8639 if (regrantPermissions)
8640 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
8641 + mSdkVersion + "; regranting permissions for external storage");
8642 mSettings.mExternalSdkPlatform = mSdkVersion;
8643
8644 // Make sure group IDs have been assigned, and any permission
8645 // changes in other apps are accounted for
Dianne Hackborne639da72012-02-21 15:11:13 -08008646 updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
8647 | (regrantPermissions
8648 ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
8649 : 0));
Kenny Root447106f2011-03-23 11:00:15 -07008650 // can downgrade to reader
8651 // Persist settings
8652 mSettings.writeLPr();
8653 }
8654 // Send a broadcast to let everyone know we are done processing
8655 if (pkgList.size() > 0) {
8656 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
8657 }
8658 // Force gc to avoid any stale parser references that we might have.
8659 if (doGc) {
8660 Runtime.getRuntime().gc();
8661 }
8662 // List stale containers and destroy stale temporary containers.
8663 if (removeCids != null) {
8664 for (String cid : removeCids) {
8665 if (cid.startsWith(mTempContainerPrefix)) {
8666 Log.i(TAG, "Destroying stale temporary container " + cid);
8667 PackageHelper.destroySdDir(cid);
8668 } else {
8669 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008670 }
8671 }
Kenny Root447106f2011-03-23 11:00:15 -07008672 }
8673 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008674
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008675 /*
Kenny Root447106f2011-03-23 11:00:15 -07008676 * Utility method to unload a list of specified containers
8677 */
Kenny Root6dceb882012-04-12 14:23:49 -07008678 private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07008679 // Just unmount all valid containers.
Kenny Root6dceb882012-04-12 14:23:49 -07008680 for (AsecInstallArgs arg : cidArgs) {
Kenny Root447106f2011-03-23 11:00:15 -07008681 synchronized (mInstallLock) {
8682 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008683 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008684 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008685 }
8686
Kenny Root447106f2011-03-23 11:00:15 -07008687 /*
8688 * Unload packages mounted on external media. This involves deleting package
8689 * data from internal structures, sending broadcasts about diabled packages,
8690 * gc'ing to free up references, unmounting all secure containers
8691 * corresponding to packages on external media, and posting a
8692 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
8693 * that we always have to post this message if status has been requested no
8694 * matter what.
8695 */
Kenny Root6dceb882012-04-12 14:23:49 -07008696 private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
Kenny Root447106f2011-03-23 11:00:15 -07008697 final boolean reportStatus) {
8698 if (DEBUG_SD_INSTALL)
8699 Log.i(TAG, "unloading media packages");
8700 ArrayList<String> pkgList = new ArrayList<String>();
Kenny Root6dceb882012-04-12 14:23:49 -07008701 ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
8702 final Set<AsecInstallArgs> keys = processCids.keySet();
8703 for (AsecInstallArgs args : keys) {
Kenny Root447106f2011-03-23 11:00:15 -07008704 String pkgName = args.getPackageName();
8705 if (DEBUG_SD_INSTALL)
8706 Log.i(TAG, "Trying to unload pkg : " + pkgName);
8707 // Delete package internally
8708 PackageRemovedInfo outInfo = new PackageRemovedInfo();
8709 synchronized (mInstallLock) {
8710 boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
8711 outInfo, false);
8712 if (res) {
8713 pkgList.add(pkgName);
8714 } else {
8715 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
8716 failedList.add(args);
8717 }
8718 }
8719 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07008720
Kenny Root447106f2011-03-23 11:00:15 -07008721 // reader
8722 synchronized (mPackages) {
8723 // We didn't update the settings after removing each package;
8724 // write them now for all packages.
8725 mSettings.writeLPr();
8726 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008727
Kenny Root447106f2011-03-23 11:00:15 -07008728 // We have to absolutely send UPDATED_MEDIA_STATUS only
8729 // after confirming that all the receivers processed the ordered
8730 // broadcast when packages get disabled, force a gc to clean things up.
8731 // and unload all the containers.
8732 if (pkgList.size() > 0) {
8733 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
8734 public void performReceive(Intent intent, int resultCode, String data,
8735 Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
8736 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
8737 reportStatus ? 1 : 0, 1, keys);
8738 mHandler.sendMessage(msg);
8739 }
8740 });
8741 } else {
8742 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
8743 keys);
8744 mHandler.sendMessage(msg);
8745 }
8746 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07008747
Kenny Root447106f2011-03-23 11:00:15 -07008748 public void movePackage(final String packageName, final IPackageMoveObserver observer,
8749 final int flags) {
8750 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
8751 int returnCode = PackageManager.MOVE_SUCCEEDED;
8752 int currFlags = 0;
8753 int newFlags = 0;
8754 // reader
8755 synchronized (mPackages) {
8756 PackageParser.Package pkg = mPackages.get(packageName);
8757 if (pkg == null) {
8758 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
8759 } else {
8760 // Disable moving fwd locked apps and system packages
8761 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
8762 Slog.w(TAG, "Cannot move system application");
8763 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root447106f2011-03-23 11:00:15 -07008764 } else if (pkg.mOperationPending) {
8765 Slog.w(TAG, "Attempt to move package which has pending operations");
8766 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
8767 } else {
8768 // Find install location first
8769 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
8770 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
8771 Slog.w(TAG, "Ambigous flags specified for move location.");
8772 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
8773 } else {
8774 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
8775 : PackageManager.INSTALL_INTERNAL;
8776 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
8777 : PackageManager.INSTALL_INTERNAL;
Kenny Rootbf023582012-05-02 16:56:15 -07008778
Kenny Root447106f2011-03-23 11:00:15 -07008779 if (newFlags == currFlags) {
8780 Slog.w(TAG, "No move required. Trying to move to same location");
8781 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Rootbf023582012-05-02 16:56:15 -07008782 } else {
8783 if (isForwardLocked(pkg)) {
8784 currFlags |= PackageManager.INSTALL_FORWARD_LOCK;
8785 newFlags |= PackageManager.INSTALL_FORWARD_LOCK;
8786 }
Kenny Root447106f2011-03-23 11:00:15 -07008787 }
8788 }
8789 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
8790 pkg.mOperationPending = true;
8791 }
8792 }
8793 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008794
Kenny Root447106f2011-03-23 11:00:15 -07008795 /*
8796 * TODO this next block probably shouldn't be inside the lock. We
8797 * can't guarantee these won't change after this is fired off
8798 * anyway.
8799 */
8800 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root6dceb882012-04-12 14:23:49 -07008801 processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1),
8802 returnCode);
Kenny Root447106f2011-03-23 11:00:15 -07008803 } else {
8804 Message msg = mHandler.obtainMessage(INIT_COPY);
8805 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -07008806 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -07008807 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Kenny Root6dceb882012-04-12 14:23:49 -07008808 pkg.applicationInfo.dataDir, pkg.applicationInfo.uid);
Kenny Root447106f2011-03-23 11:00:15 -07008809 msg.obj = mp;
8810 mHandler.sendMessage(msg);
8811 }
8812 }
8813 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008814
Kenny Root447106f2011-03-23 11:00:15 -07008815 private void processPendingMove(final MoveParams mp, final int currentStatus) {
8816 // Queue up an async operation since the package deletion may take a
8817 // little while.
8818 mHandler.post(new Runnable() {
8819 public void run() {
8820 // TODO fix this; this does nothing.
8821 mHandler.removeCallbacks(this);
8822 int returnCode = currentStatus;
8823 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
8824 int uidArr[] = null;
8825 ArrayList<String> pkgList = null;
8826 synchronized (mPackages) {
8827 PackageParser.Package pkg = mPackages.get(mp.packageName);
8828 if (pkg == null) {
8829 Slog.w(TAG, " Package " + mp.packageName
8830 + " doesn't exist. Aborting move");
8831 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
8832 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
8833 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
8834 + mp.srcArgs.getCodePath() + " to "
8835 + pkg.applicationInfo.sourceDir
8836 + " Aborting move and returning error");
8837 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
8838 } else {
8839 uidArr = new int[] {
8840 pkg.applicationInfo.uid
8841 };
8842 pkgList = new ArrayList<String>();
8843 pkgList.add(mp.packageName);
8844 }
8845 }
8846 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
8847 // Send resources unavailable broadcast
8848 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
8849 // Update package code and resource paths
8850 synchronized (mInstallLock) {
8851 synchronized (mPackages) {
8852 PackageParser.Package pkg = mPackages.get(mp.packageName);
8853 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -07008854 if (pkg == null) {
8855 Slog.w(TAG, " Package " + mp.packageName
8856 + " doesn't exist. Aborting move");
8857 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -07008858 } else if (!mp.srcArgs.getCodePath().equals(
8859 pkg.applicationInfo.sourceDir)) {
8860 Slog.w(TAG, "Package " + mp.packageName
8861 + " code path changed from " + mp.srcArgs.getCodePath()
8862 + " to " + pkg.applicationInfo.sourceDir
8863 + " Aborting move and returning error");
8864 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
8865 } else {
8866 final String oldCodePath = pkg.mPath;
8867 final String newCodePath = mp.targetArgs.getCodePath();
8868 final String newResPath = mp.targetArgs.getResourcePath();
8869 final String newNativePath = mp.targetArgs
8870 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -07008871
Kenny Rootbf023582012-05-02 16:56:15 -07008872 try {
8873 final File newNativeDir = new File(newNativePath);
8874
8875 final String libParentDir = newNativeDir.getParentFile()
8876 .getCanonicalPath();
8877 if (newNativeDir.getParentFile().getCanonicalPath()
8878 .equals(pkg.applicationInfo.dataDir)) {
8879 if (mInstaller
8880 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
8881 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
8882 } else {
8883 NativeLibraryHelper.copyNativeBinariesIfNeededLI(
8884 new File(newCodePath), newNativeDir);
8885 }
Kenny Root6a6b0072010-10-07 16:46:10 -07008886 } else {
Kenny Rootbf023582012-05-02 16:56:15 -07008887 if (mInstaller.linkNativeLibraryDirectory(
8888 pkg.applicationInfo.dataDir, newNativePath) < 0) {
8889 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
8890 }
Kenny Root6a6b0072010-10-07 16:46:10 -07008891 }
Kenny Rootbf023582012-05-02 16:56:15 -07008892 } catch (IOException e) {
8893 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Kenny Root6a6b0072010-10-07 16:46:10 -07008894 }
8895
Kenny Rootbf023582012-05-02 16:56:15 -07008896
Kenny Root6a6b0072010-10-07 16:46:10 -07008897 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
8898 pkg.mPath = newCodePath;
8899 // Move dex files around
8900 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
8901 // Moving of dex files failed. Set
8902 // error code and abort move.
8903 pkg.mPath = pkg.mScanPath;
8904 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
8905 }
8906 }
8907
8908 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -07008909 pkg.mScanPath = newCodePath;
8910 pkg.applicationInfo.sourceDir = newCodePath;
8911 pkg.applicationInfo.publicSourceDir = newResPath;
8912 pkg.applicationInfo.nativeLibraryDir = newNativePath;
8913 PackageSetting ps = (PackageSetting) pkg.mExtras;
8914 ps.codePath = new File(pkg.applicationInfo.sourceDir);
8915 ps.codePathString = ps.codePath.getPath();
8916 ps.resourcePath = new File(
8917 pkg.applicationInfo.publicSourceDir);
8918 ps.resourcePathString = ps.resourcePath.getPath();
8919 ps.nativeLibraryPathString = newNativePath;
8920 // Set the application info flag
8921 // correctly.
8922 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
8923 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
8924 } else {
8925 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
8926 }
8927 ps.setFlags(pkg.applicationInfo.flags);
8928 mAppDirs.remove(oldCodePath);
8929 mAppDirs.put(newCodePath, pkg);
8930 // Persist settings
8931 mSettings.writeLPr();
8932 }
8933 }
8934 }
8935 }
8936 // Send resources available broadcast
8937 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
8938 }
8939 }
8940 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
8941 // Clean up failed installation
8942 if (mp.targetArgs != null) {
Kenny Root6dceb882012-04-12 14:23:49 -07008943 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
8944 -1);
Kenny Root447106f2011-03-23 11:00:15 -07008945 }
8946 } else {
8947 // Force a gc to clear things up.
8948 Runtime.getRuntime().gc();
8949 // Delete older code
8950 synchronized (mInstallLock) {
8951 mp.srcArgs.doPostDeleteLI(true);
8952 }
8953 }
Kenny Rootdeb11262010-08-02 11:36:21 -07008954
Kenny Root447106f2011-03-23 11:00:15 -07008955 // Allow more operations on this file if we didn't fail because
8956 // an operation was already pending for this package.
8957 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
8958 synchronized (mPackages) {
8959 PackageParser.Package pkg = mPackages.get(mp.packageName);
8960 if (pkg != null) {
8961 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -07008962 }
8963 }
Kenny Root447106f2011-03-23 11:00:15 -07008964 }
Kenny Rootdeb11262010-08-02 11:36:21 -07008965
Kenny Root447106f2011-03-23 11:00:15 -07008966 IPackageMoveObserver observer = mp.observer;
8967 if (observer != null) {
8968 try {
8969 observer.packageMoved(mp.packageName, returnCode);
8970 } catch (RemoteException e) {
8971 Log.i(TAG, "Observer no longer exists.");
8972 }
8973 }
8974 }
8975 });
8976 }
8977
8978 public boolean setInstallLocation(int loc) {
8979 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
8980 null);
8981 if (getInstallLocation() == loc) {
8982 return true;
8983 }
8984 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
8985 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
8986 android.provider.Settings.System.putInt(mContext.getContentResolver(),
8987 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
8988 return true;
8989 }
8990 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008991 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -07008992
Kenny Root447106f2011-03-23 11:00:15 -07008993 public int getInstallLocation() {
8994 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
8995 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION,
8996 PackageHelper.APP_INSTALL_AUTO);
8997 }
Amith Yamasani0b285492011-04-14 17:35:23 -07008998
8999 public UserInfo createUser(String name, int flags) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009000 // TODO(kroot): Add a real permission for creating users
9001 enforceSystemOrRoot("Only the system can create users");
9002
Amith Yamasani13593602012-03-22 16:16:17 -07009003 UserInfo userInfo = sUserManager.createUser(name, flags);
9004 if (userInfo != null) {
9005 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
9006 addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
9007 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9008 }
Amith Yamasani0b285492011-04-14 17:35:23 -07009009 return userInfo;
9010 }
9011
9012 public boolean removeUser(int userId) {
Kenny Root461ff1f2011-08-09 09:43:03 -07009013 // TODO(kroot): Add a real permission for removing users
9014 enforceSystemOrRoot("Only the system can remove users");
9015
Amith Yamasani13593602012-03-22 16:16:17 -07009016 if (userId == 0 || !sUserManager.exists(userId)) {
Amith Yamasani0b285492011-04-14 17:35:23 -07009017 return false;
9018 }
Amith Yamasani13593602012-03-22 16:16:17 -07009019
9020 cleanUpUser(userId);
9021
9022 if (sUserManager.removeUser(userId)) {
9023 // Let other services shutdown any activity
9024 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
9025 addedIntent.putExtra(Intent.EXTRA_USERID, userId);
9026 mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
9027 }
9028 sUserManager.removePackageFolders(userId);
Amith Yamasani0b285492011-04-14 17:35:23 -07009029 return true;
9030 }
Kenny Root0aaa0d92011-09-12 16:42:55 -07009031
Amith Yamasani13593602012-03-22 16:16:17 -07009032 private void cleanUpUser(int userId) {
9033 // Disable all the packages for the user first
9034 synchronized (mPackages) {
9035 Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
9036 for (Entry<String, PackageSetting> entry : entries) {
9037 entry.getValue().removeUser(userId);
9038 }
9039 if (mDirtyUsers.remove(userId));
9040 mSettings.removeUserLPr(userId);
9041 }
9042 }
9043
Kenny Root0aaa0d92011-09-12 16:42:55 -07009044 @Override
9045 public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
9046 mContext.enforceCallingOrSelfPermission(
9047 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
9048 "Only package verification agents can read the verifier device identity");
9049
9050 synchronized (mPackages) {
9051 return mSettings.getVerifierDeviceIdentityLPw();
9052 }
9053 }
Amith Yamasani742a6712011-05-04 14:49:28 -07009054
Amith Yamasani13593602012-03-22 16:16:17 -07009055 @Override
Amith Yamasani742a6712011-05-04 14:49:28 -07009056 public List<UserInfo> getUsers() {
Amith Yamasani13593602012-03-22 16:16:17 -07009057 enforceSystemOrRoot("Only the system can query users");
9058 return sUserManager.getUsers();
9059 }
9060
9061 @Override
9062 public UserInfo getUser(int userId) {
9063 enforceSystemOrRoot("Only the system can remove users");
9064 return sUserManager.getUser(userId);
9065 }
9066
9067 @Override
9068 public void updateUserName(int userId, String name) {
9069 enforceSystemOrRoot("Only the system can rename users");
9070 sUserManager.updateUserName(userId, name);
Amith Yamasani742a6712011-05-04 14:49:28 -07009071 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009072
9073 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009074 public void setPermissionEnforced(String permission, boolean enforced) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009075 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
9076 if (READ_EXTERNAL_STORAGE.equals(permission)) {
9077 synchronized (mPackages) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009078 if (mSettings.mReadExternalStorageEnforced != enforced) {
9079 mSettings.mReadExternalStorageEnforced = enforced;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009080 mSettings.writeLPr();
Jeff Sharkeyb9a07012012-03-22 17:00:04 -07009081
9082 // kill any non-foreground processes so we restart them and
9083 // grant/revoke the GID.
9084 final IActivityManager am = ActivityManagerNative.getDefault();
9085 if (am != null) {
9086 final long token = Binder.clearCallingIdentity();
9087 try {
9088 am.killProcessesBelowForeground("setPermissionEnforcement");
9089 } catch (RemoteException e) {
9090 } finally {
9091 Binder.restoreCallingIdentity(token);
9092 }
9093 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009094 }
9095 }
9096 } else {
9097 throw new IllegalArgumentException("No selective enforcement for " + permission);
9098 }
9099 }
9100
9101 @Override
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009102 public boolean isPermissionEnforced(String permission) {
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009103 mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009104 synchronized (mPackages) {
9105 return isPermissionEnforcedLocked(permission);
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009106 }
9107 }
9108
9109 private boolean isPermissionEnforcedLocked(String permission) {
9110 if (READ_EXTERNAL_STORAGE.equals(permission)) {
Jeff Sharkey5d32e772012-04-12 15:59:23 -07009111 return mSettings.mReadExternalStorageEnforced;
9112 } else {
9113 return true;
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009114 }
Jeff Sharkeyedc84ee82012-03-19 16:52:26 -07009115 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116}