blob: de439caff67c0c4de49b68b0baa738db22c64273 [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
Kenny Root27989422011-02-23 16:28:26 -080019import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
20import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
21import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
22
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080023import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import com.android.internal.app.ResolverActivity;
Kenny Root85387d72010-08-26 10:13:11 -070025import com.android.internal.content.NativeLibraryHelper;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080026import com.android.internal.content.PackageHelper;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080027import com.android.internal.util.XmlUtils;
Kenny Rootcf0b38c2011-03-22 14:17:59 -070028import com.android.server.DeviceStorageMonitorService;
29import com.android.server.EventLogTags;
30import com.android.server.IntentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
Jason parksa3cdaa52011-01-13 14:15:43 -060032import org.xmlpull.v1.XmlPullParser;
33import org.xmlpull.v1.XmlPullParserException;
Jason parksa3cdaa52011-01-13 14:15:43 -060034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.app.ActivityManagerNative;
36import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080037import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080038import android.app.backup.IBackupManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060039import android.content.ComponentName;
Kenny Root27989422011-02-23 16:28:26 -080040import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070041import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.Intent;
43import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070044import android.content.IntentSender;
Jason parks1125d782011-01-12 09:47:26 -060045import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060046import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.content.pm.ActivityInfo;
48import android.content.pm.ApplicationInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070049import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.pm.IPackageDataObserver;
51import android.content.pm.IPackageDeleteObserver;
52import android.content.pm.IPackageInstallObserver;
53import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080054import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.pm.IPackageStatsObserver;
56import android.content.pm.InstrumentationInfo;
57import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080058import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.pm.PackageManager;
Jason parksa3cdaa52011-01-13 14:15:43 -060060import android.content.pm.PackageParser;
Kenny Root27989422011-02-23 16:28:26 -080061import android.content.pm.PackageStats;
Jason parksa3cdaa52011-01-13 14:15:43 -060062import android.content.pm.PermissionGroupInfo;
Kenny Root27989422011-02-23 16:28:26 -080063import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ProviderInfo;
65import android.content.pm.ResolveInfo;
66import android.content.pm.ServiceInfo;
67import android.content.pm.Signature;
Amith Yamasani0b285492011-04-14 17:35:23 -070068import android.content.pm.UserInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.net.Uri;
70import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070071import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.os.Bundle;
Kenny Root27989422011-02-23 16:28:26 -080073import android.os.Environment;
74import android.os.FileObserver;
75import android.os.FileUtils;
76import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080078import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070079import android.os.Looper;
80import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.ParcelFileDescriptor;
83import android.os.Process;
Kenny Root27989422011-02-23 16:28:26 -080084import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.ServiceManager;
86import android.os.SystemClock;
87import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080088import android.security.SystemKeyStore;
Kenny Root27989422011-02-23 16:28:26 -080089import android.util.DisplayMetrics;
90import android.util.EventLog;
91import android.util.Log;
92import android.util.LogPrinter;
93import android.util.Slog;
94import android.util.SparseArray;
95import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.view.Display;
97import android.view.WindowManager;
98
99import java.io.File;
100import java.io.FileDescriptor;
101import java.io.FileInputStream;
102import java.io.FileNotFoundException;
103import java.io.FileOutputStream;
104import java.io.FileReader;
105import java.io.FilenameFilter;
106import java.io.IOException;
107import java.io.InputStream;
108import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800109import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800110import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.util.ArrayList;
112import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700113import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.util.Collections;
115import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800116import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.util.Enumeration;
118import java.util.HashMap;
119import java.util.HashSet;
120import java.util.Iterator;
121import java.util.List;
122import java.util.Map;
123import java.util.Set;
124import java.util.zip.ZipEntry;
125import java.util.zip.ZipFile;
126import java.util.zip.ZipOutputStream;
127
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700128/**
129 * Keep track of all those .apks everywhere.
130 *
131 * This is very central to the platform's security; please run the unit
132 * tests whenever making modifications here:
133 *
134mmm frameworks/base/tests/AndroidTests
135adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
136adb 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 -0700137 *
138 * {@hide}
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700139 */
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700140public class PackageManagerService extends IPackageManager.Stub {
141 static final String TAG = "PackageManager";
142 static final boolean DEBUG_SETTINGS = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 private static final boolean DEBUG_PREFERRED = false;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700144 static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800145 private static final boolean DEBUG_INSTALL = false;
Kenny Root9718cf52011-02-23 16:45:26 -0800146 private static final boolean DEBUG_REMOVE = false;
147 private static final boolean DEBUG_SHOW_INFO = false;
148 private static final boolean DEBUG_PACKAGE_INFO = false;
149 private static final boolean DEBUG_INTENT_MATCHING = false;
150 private static final boolean DEBUG_PACKAGE_SCANNING = false;
151 private static final boolean DEBUG_APP_DIR_OBSERVER = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700153 static final boolean MULTIPLE_APPLICATION_UIDS = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400155 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700156 private static final int NFC_UID = Process.NFC_UID;
Brian Carlstrom8c2a1a92011-04-08 13:44:08 -0700157 private static final int KEYCHAIN_UID = Process.KEYCHAIN_UID;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700158 static final int FIRST_APPLICATION_UID =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 Process.FIRST_APPLICATION_UID;
Kenny Rootcf0b38c2011-03-22 14:17:59 -0700160 static final int MAX_APPLICATION_UIDS = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final boolean GET_CERTIFICATES = true;
163
164 private static final int REMOVE_EVENTS =
165 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
166 private static final int ADD_EVENTS =
167 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
168
169 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800170 // Suffix used during package installation when copying/moving
171 // package apks to install directory.
172 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173
174 static final int SCAN_MONITOR = 1<<0;
175 static final int SCAN_NO_DEX = 1<<1;
176 static final int SCAN_FORCE_DEX = 1<<2;
177 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800178 static final int SCAN_NEW_INSTALL = 1<<4;
179 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700180 static final int SCAN_UPDATE_TIME = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700182 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700183
184 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
185
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800186 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700187 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800188 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700189
Kenny Root85387d72010-08-26 10:13:11 -0700190 private static final String LIB_DIR_NAME = "lib";
191
Kenny Rootc78a8072010-07-27 15:18:38 -0700192 static final String mTempContainerPrefix = "smdl2tmp";
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
195 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700196 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
Dianne Hackborn851a5412009-05-08 12:06:44 -0700198 final int mSdkVersion = Build.VERSION.SDK_INT;
199 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
200 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 final Context mContext;
203 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700204 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 final DisplayMetrics mMetrics;
206 final int mDefParseFlags;
207 final String[] mSeparateProcesses;
208
209 // This is where all application persistent data goes.
210 final File mAppDataDir;
211
Amith Yamasani0b285492011-04-14 17:35:23 -0700212 // This is where all application persistent data goes for secondary users.
213 final File mUserAppDataDir;
214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 // This is the object monitoring the framework dir.
216 final FileObserver mFrameworkInstallObserver;
217
218 // This is the object monitoring the system app dir.
219 final FileObserver mSystemInstallObserver;
220
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700221 // This is the object monitoring the system app dir.
222 final FileObserver mVendorInstallObserver;
223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 // This is the object monitoring mAppInstallDir.
225 final FileObserver mAppInstallObserver;
226
227 // This is the object monitoring mDrmAppPrivateInstallDir.
228 final FileObserver mDrmAppInstallObserver;
229
230 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
231 // LOCK HELD. Can be called with mInstallLock held.
232 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 final File mFrameworkDir;
235 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700236 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700238 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239
240 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
241 // apps.
242 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Lock for state used when installing and doing other long running
247 // operations. Methods that must be called with this lock held have
248 // the prefix "LI".
249 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 // These are the directories in the 3rd party applications installed dir
252 // that we have currently loaded packages from. Keys are the application's
253 // installed zip file (absolute codePath), and values are Package.
254 final HashMap<String, PackageParser.Package> mAppDirs =
255 new HashMap<String, PackageParser.Package>();
256
257 // Information for the parser to write more useful error messages.
258 File mScanningPath;
259 int mLastScanError;
260
261 final int[] mOutPermissions = new int[3];
262
263 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 // Keys are String (package name), values are Package. This also serves
266 // as the lock for the global state. Methods that must be called with
267 // this lock held have the prefix "LP".
268 final HashMap<String, PackageParser.Package> mPackages =
269 new HashMap<String, PackageParser.Package>();
270
271 final Settings mSettings;
272 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
275 int[] mGlobalGids;
276
277 // These are the built-in uid -> permission mappings that were read from the
278 // etc/permissions.xml file.
279 final SparseArray<HashSet<String>> mSystemPermissions =
280 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 // These are the built-in shared libraries that were read from the
283 // etc/permissions.xml file.
284 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800285
Dianne Hackborn49237342009-08-27 20:08:01 -0700286 // Temporary for building the final shared libraries for an .apk.
287 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800288
Dianne Hackborn49237342009-08-27 20:08:01 -0700289 // These are the features this devices supports that were read from the
290 // etc/permissions.xml file.
291 final HashMap<String, FeatureInfo> mAvailableFeatures =
292 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 // All available activities, for your resolving pleasure.
295 final ActivityIntentResolver mActivities =
296 new ActivityIntentResolver();
297
298 // All available receivers, for your resolving pleasure.
299 final ActivityIntentResolver mReceivers =
300 new ActivityIntentResolver();
301
302 // All available services, for your resolving pleasure.
303 final ServiceIntentResolver mServices = new ServiceIntentResolver();
304
305 // Keys are String (provider class name), values are Provider.
306 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
307 new HashMap<ComponentName, PackageParser.Provider>();
308
309 // Mapping from provider base names (first directory in content URI codePath)
310 // to the provider information.
311 final HashMap<String, PackageParser.Provider> mProviders =
312 new HashMap<String, PackageParser.Provider>();
313
314 // Mapping from instrumentation class names to info about them.
315 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
316 new HashMap<ComponentName, PackageParser.Instrumentation>();
317
318 // Mapping from permission names to info about them.
319 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
320 new HashMap<String, PackageParser.PermissionGroup>();
321
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800322 // Packages whose data we have transfered into another package, thus
323 // should no longer exist.
324 final HashSet<String> mTransferedPackages = new HashSet<String>();
325
Dianne Hackborn854060af2009-07-09 18:14:31 -0700326 // Broadcast actions that are only available to the system.
327 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 boolean mSystemReady;
330 boolean mSafeMode;
331 boolean mHasSystemUidErrors;
332
333 ApplicationInfo mAndroidApplication;
334 final ActivityInfo mResolveActivity = new ActivityInfo();
335 final ResolveInfo mResolveInfo = new ResolveInfo();
336 ComponentName mResolveComponentName;
337 PackageParser.Package mPlatformPackage;
338
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700339 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800340 final HashMap<String, ArrayList<String>> mPendingBroadcasts
341 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800342 // Service Connection to remote media container service to copy
343 // package uri's from external media onto secure containers
344 // or internal storage.
345 private IMediaContainerService mContainerService = null;
346
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700347 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800348 static final int MCS_BOUND = 3;
349 static final int END_COPY = 4;
350 static final int INIT_COPY = 5;
351 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800352 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800353 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800354 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800355 static final int MCS_RECONNECT = 10;
356 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700357 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700358 static final int WRITE_SETTINGS = 13;
Dianne Hackborne7f97212011-02-24 14:40:20 -0800359 static final int WRITE_STOPPED_PACKAGES = 14;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700360
361 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800362
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700363 // Delay time in millisecs
364 static final int BROADCAST_DELAY = 10 * 1000;
Kenny Root9718cf52011-02-23 16:45:26 -0800365
Amith Yamasani0b285492011-04-14 17:35:23 -0700366 final UserManager mUserManager;
367
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800368 final private DefaultContainerConnection mDefContainerConn =
369 new DefaultContainerConnection();
370 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800371 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800372 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800373 IMediaContainerService imcs =
374 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800375 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800376 }
377
378 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800379 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800380 }
381 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700382
Christopher Tate1bb69062010-02-19 17:02:12 -0800383 // Recordkeeping of restore-after-install operations that are currently in flight
384 // between the Package Manager and the Backup Manager
385 class PostInstallData {
386 public InstallArgs args;
387 public PackageInstalledInfo res;
388
389 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
390 args = _a;
391 res = _r;
392 }
393 };
394 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
395 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
396
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700397 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800398 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800399 final ArrayList<HandlerParams> mPendingInstalls =
400 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800401
402 private boolean connectToService() {
403 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
404 " DefaultContainerService");
405 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700406 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800407 if (mContext.bindService(service, mDefContainerConn,
408 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700409 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800410 mBound = true;
411 return true;
412 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700413 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800414 return false;
415 }
416
417 private void disconnectService() {
418 mContainerService = null;
419 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700420 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800421 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700422 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800423 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800424
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700425 PackageHandler(Looper looper) {
426 super(looper);
427 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700428
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700429 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700430 try {
431 doHandleMessage(msg);
432 } finally {
433 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
434 }
435 }
436
437 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700438 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800439 case INIT_COPY: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800440 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800441 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800442 int idx = mPendingInstalls.size();
443 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
444 // If a bind was already initiated we dont really
445 // need to do anything. The pending install
446 // will be processed later on.
447 if (!mBound) {
448 // If this is the only one pending we might
449 // have to bind to the service again.
450 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800451 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800452 params.serviceError();
453 return;
454 } else {
455 // Once we bind to the service, the first
456 // pending request will be processed.
457 mPendingInstalls.add(idx, params);
458 }
459 } else {
460 mPendingInstalls.add(idx, params);
461 // Already bound to the service. Just make
462 // sure we trigger off processing the first request.
463 if (idx == 0) {
464 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800465 }
466 }
467 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800468 }
469 case MCS_BOUND: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800470 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800471 if (msg.obj != null) {
472 mContainerService = (IMediaContainerService) msg.obj;
473 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800474 if (mContainerService == null) {
475 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800476 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800477 for (HandlerParams params : mPendingInstalls) {
478 mPendingInstalls.remove(0);
479 // Indicate service bind error
480 params.serviceError();
481 }
482 mPendingInstalls.clear();
483 } else if (mPendingInstalls.size() > 0) {
484 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800485 if (params != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800486 params.startCopy();
487 }
488 } else {
489 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800490 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800491 }
492 break;
493 }
494 case MCS_RECONNECT : {
495 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
496 if (mPendingInstalls.size() > 0) {
497 if (mBound) {
498 disconnectService();
499 }
500 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800501 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800502 for (HandlerParams params : mPendingInstalls) {
503 mPendingInstalls.remove(0);
504 // Indicate service bind error
505 params.serviceError();
506 }
507 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800508 }
509 }
510 break;
511 }
512 case MCS_UNBIND : {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800513 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
514 // Delete pending install
515 if (mPendingInstalls.size() > 0) {
516 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800517 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800518 if (mPendingInstalls.size() == 0) {
519 if (mBound) {
520 disconnectService();
521 }
522 } else {
523 // There are more pending requests in queue.
524 // Just post MCS_BOUND message to trigger processing
525 // of next pending install.
526 mHandler.sendEmptyMessage(MCS_BOUND);
527 }
528 break;
529 }
530 case MCS_GIVE_UP: {
531 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
Kenny Root60f7ad82011-03-22 12:49:06 -0700532 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800533 break;
534 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700535 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800536 String packages[];
Kenny Root60f7ad82011-03-22 12:49:06 -0700537 ArrayList<String> components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700538 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700539 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700540 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700541 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800542 if (mPendingBroadcasts == null) {
543 return;
544 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700545 size = mPendingBroadcasts.size();
546 if (size <= 0) {
547 // Nothing to be done. Just return
548 return;
549 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800550 packages = new String[size];
551 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700552 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800553 Iterator<HashMap.Entry<String, ArrayList<String>>>
554 it = mPendingBroadcasts.entrySet().iterator();
555 int i = 0;
556 while (it.hasNext() && i < size) {
557 HashMap.Entry<String, ArrayList<String>> ent = it.next();
558 packages[i] = ent.getKey();
559 components[i] = ent.getValue();
560 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700561 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800562 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700563 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800564 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700565 mPendingBroadcasts.clear();
566 }
567 // Send broadcasts
568 for (int i = 0; i < size; i++) {
Kenny Root60f7ad82011-03-22 12:49:06 -0700569 sendPackageChangedBroadcast(packages[i], true, components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700570 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700571 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700572 break;
573 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800574 case START_CLEANING_PACKAGE: {
575 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700576 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800577 synchronized (mPackages) {
578 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
579 mSettings.mPackagesToBeCleaned.add(packageName);
580 }
581 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700582 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800583 startCleaningPackages();
584 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800585 case POST_INSTALL: {
586 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
587 PostInstallData data = mRunningInstalls.get(msg.arg1);
588 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700589 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800590
591 if (data != null) {
592 InstallArgs args = data.args;
593 PackageInstalledInfo res = data.res;
594
595 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700596 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800597 Bundle extras = new Bundle(1);
598 extras.putInt(Intent.EXTRA_UID, res.uid);
599 final boolean update = res.removedInfo.removedPackage != null;
600 if (update) {
601 extras.putBoolean(Intent.EXTRA_REPLACING, true);
602 }
603 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
604 res.pkg.applicationInfo.packageName,
Dianne Hackborne7f97212011-02-24 14:40:20 -0800605 extras, null, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800606 if (update) {
607 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
608 res.pkg.applicationInfo.packageName,
Dianne Hackborne7f97212011-02-24 14:40:20 -0800609 extras, null, null);
610 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
611 null, null,
612 res.pkg.applicationInfo.packageName, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800613 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700614 if (res.removedInfo.args != null) {
615 // Remove the replaced package's older resources safely now
616 deleteOld = true;
617 }
618 }
619 // Force a gc to clear up things
620 Runtime.getRuntime().gc();
621 // We delete after a gc for applications on sdcard.
622 if (deleteOld) {
623 synchronized (mInstallLock) {
624 res.removedInfo.args.doPostDeleteLI(true);
625 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800626 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800627 if (args.observer != null) {
628 try {
629 args.observer.packageInstalled(res.name, res.returnCode);
630 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800631 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800632 }
633 }
634 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800635 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800636 }
637 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700638 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700639 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
640 boolean reportStatus = msg.arg1 == 1;
641 boolean doGc = msg.arg2 == 1;
642 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
643 if (doGc) {
644 // Force a gc to clear up stale containers.
645 Runtime.getRuntime().gc();
646 }
647 if (msg.obj != null) {
648 Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
649 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
650 // Unload containers
651 unloadAllContainers(args);
652 }
653 if (reportStatus) {
654 try {
655 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
656 PackageHelper.getMountService().finishMediaUpdate();
657 } catch (RemoteException e) {
658 Log.e(TAG, "MountService not running?");
659 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700660 }
661 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700662 case WRITE_SETTINGS: {
663 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
664 synchronized (mPackages) {
665 removeMessages(WRITE_SETTINGS);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800666 removeMessages(WRITE_STOPPED_PACKAGES);
Kenny Root447106f2011-03-23 11:00:15 -0700667 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700668 }
669 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
670 } break;
Dianne Hackborne7f97212011-02-24 14:40:20 -0800671 case WRITE_STOPPED_PACKAGES: {
672 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
673 synchronized (mPackages) {
674 removeMessages(WRITE_STOPPED_PACKAGES);
Kenny Root447106f2011-03-23 11:00:15 -0700675 mSettings.writeStoppedLPr();
Dianne Hackborne7f97212011-02-24 14:40:20 -0800676 }
677 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
678 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700679 }
680 }
681 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800682
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700683 void scheduleWriteSettingsLocked() {
684 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
685 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
686 }
687 }
688
Dianne Hackborne7f97212011-02-24 14:40:20 -0800689 void scheduleWriteStoppedPackagesLocked() {
690 if (!mHandler.hasMessages(WRITE_STOPPED_PACKAGES)) {
691 mHandler.sendEmptyMessageDelayed(WRITE_STOPPED_PACKAGES, WRITE_SETTINGS_DELAY);
692 }
693 }
694
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800695 static boolean installOnSd(int flags) {
696 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700697 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800698 return false;
699 }
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700700 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
701 return true;
702 }
703 return false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800704 }
705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 public static final IPackageManager main(Context context, boolean factoryTest) {
707 PackageManagerService m = new PackageManagerService(context, factoryTest);
708 ServiceManager.addService("package", m);
709 return m;
710 }
711
712 static String[] splitString(String str, char sep) {
713 int count = 1;
714 int i = 0;
715 while ((i=str.indexOf(sep, i)) >= 0) {
716 count++;
717 i++;
718 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 String[] res = new String[count];
721 i=0;
722 count = 0;
723 int lastI=0;
724 while ((i=str.indexOf(sep, i)) >= 0) {
725 res[count] = str.substring(lastI, i);
726 count++;
727 i++;
728 lastI = i;
729 }
730 res[count] = str.substring(lastI, str.length());
731 return res;
732 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800735 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800739 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 mContext = context;
743 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700744 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 mMetrics = new DisplayMetrics();
746 mSettings = new Settings();
Kenny Root447106f2011-03-23 11:00:15 -0700747 mSettings.addSharedUserLPw("android.uid.system",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
Kenny Root447106f2011-03-23 11:00:15 -0700749 mSettings.addSharedUserLPw("android.uid.phone",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 MULTIPLE_APPLICATION_UIDS
751 ? RADIO_UID : FIRST_APPLICATION_UID,
752 ApplicationInfo.FLAG_SYSTEM);
Kenny Root447106f2011-03-23 11:00:15 -0700753 mSettings.addSharedUserLPw("android.uid.log",
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400754 MULTIPLE_APPLICATION_UIDS
755 ? LOG_UID : FIRST_APPLICATION_UID,
756 ApplicationInfo.FLAG_SYSTEM);
Kenny Root447106f2011-03-23 11:00:15 -0700757 mSettings.addSharedUserLPw("android.uid.nfc",
Nick Pellycd0e8392010-10-13 17:25:24 -0700758 MULTIPLE_APPLICATION_UIDS
759 ? NFC_UID : FIRST_APPLICATION_UID,
760 ApplicationInfo.FLAG_SYSTEM);
Brian Carlstrom8c2a1a92011-04-08 13:44:08 -0700761 mSettings.addSharedUserLPw("android.uid.keychain",
762 MULTIPLE_APPLICATION_UIDS
763 ? KEYCHAIN_UID : FIRST_APPLICATION_UID,
764 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765
766 String separateProcesses = SystemProperties.get("debug.separate_processes");
767 if (separateProcesses != null && separateProcesses.length() > 0) {
768 if ("*".equals(separateProcesses)) {
769 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
770 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800771 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 } else {
773 mDefParseFlags = 0;
774 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800775 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 + separateProcesses);
777 }
778 } else {
779 mDefParseFlags = 0;
780 mSeparateProcesses = null;
781 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 Installer installer = new Installer();
784 // Little hacky thing to check if installd is here, to determine
785 // whether we are running on the simulator and thus need to take
786 // care of building the /data file structure ourself.
787 // (apparently the sim now has a working installer)
788 if (installer.ping() && Process.supportsProcesses()) {
789 mInstaller = installer;
790 } else {
791 mInstaller = null;
792 }
793
794 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
795 Display d = wm.getDefaultDisplay();
796 d.getMetrics(mMetrics);
797
798 synchronized (mInstallLock) {
Kenny Root447106f2011-03-23 11:00:15 -0700799 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 synchronized (mPackages) {
801 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700802 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 File dataDir = Environment.getDataDirectory();
805 mAppDataDir = new File(dataDir, "data");
Amith Yamasani0b285492011-04-14 17:35:23 -0700806 mUserAppDataDir = new File(dataDir, "user");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
808
Amith Yamasani0b285492011-04-14 17:35:23 -0700809 mUserManager = new UserManager(mInstaller, mUserAppDataDir);
810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 if (mInstaller == null) {
812 // Make sure these dirs exist, when we are running in
813 // the simulator.
814 // Make a wide-open directory for random misc stuff.
815 File miscDir = new File(dataDir, "misc");
816 miscDir.mkdirs();
817 mAppDataDir.mkdirs();
Amith Yamasani0b285492011-04-14 17:35:23 -0700818 mUserAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 mDrmAppPrivateInstallDir.mkdirs();
820 }
821
822 readPermissions();
823
Kenny Root447106f2011-03-23 11:00:15 -0700824 mRestoredSettings = mSettings.readLPw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800826
827 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800829
Suchi Amalapurapudaec1722010-01-14 21:25:16 -0800830 // Set flag to monitor and not change apk file paths when
831 // scanning install directories.
832 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700833 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800834 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800835 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700836 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700841 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700844 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 /**
847 * Out of paranoia, ensure that everything in the boot class
848 * path has been dexed.
849 */
850 String bootClassPath = System.getProperty("java.boot.class.path");
851 if (bootClassPath != null) {
852 String[] paths = splitString(bootClassPath, ':');
853 for (int i=0; i<paths.length; i++) {
854 try {
855 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
856 libFiles.add(paths[i]);
857 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700858 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 }
860 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800861 Slog.w(TAG, "Boot class path not found: " + paths[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800863 Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 }
865 }
866 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800867 Slog.w(TAG, "No BOOTCLASSPATH found!");
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 /**
871 * Also ensure all external libraries have had dexopt run on them.
872 */
873 if (mSharedLibraries.size() > 0) {
874 Iterator<String> libs = mSharedLibraries.values().iterator();
875 while (libs.hasNext()) {
876 String lib = libs.next();
877 try {
878 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
879 libFiles.add(lib);
880 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700881 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 }
883 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800884 Slog.w(TAG, "Library not found: " + lib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800886 Slog.w(TAG, "Exception reading library: " + lib, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 }
888 }
889 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 // Gross hack for now: we know this file doesn't contain any
892 // code, so don't dexopt it to avoid the resulting log spew.
893 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 /**
896 * And there are a number of commands implemented in Java, which
897 * we currently need to do the dexopt on so that they can be
898 * run from a non-root shell.
899 */
900 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700901 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 for (int i=0; i<frameworkFiles.length; i++) {
903 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
904 String path = libPath.getPath();
905 // Skip the file if we alrady did it.
906 if (libFiles.contains(path)) {
907 continue;
908 }
909 // Skip the file if it is not a type we want to dexopt.
910 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
911 continue;
912 }
913 try {
914 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
915 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700916 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 }
918 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800919 Slog.w(TAG, "Jar not found: " + path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800921 Slog.w(TAG, "Exception reading jar: " + path, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 }
923 }
924 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800925
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700926 if (didDexOpt) {
927 // If we had to do a dexopt of one of the previous
928 // things, then something on the system has changed.
929 // Consider this significant, and wipe away all other
930 // existing dexopt files to ensure we don't leave any
931 // dangling around.
932 String[] files = mDalvikCacheDir.list();
933 if (files != null) {
934 for (int i=0; i<files.length; i++) {
935 String fn = files[i];
936 if (fn.startsWith("data@app@")
937 || fn.startsWith("data@app-private@")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800938 Slog.i(TAG, "Pruning dalvik file: " + fn);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700939 (new File(mDalvikCacheDir, fn)).delete();
940 }
941 }
942 }
943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800945
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800946 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 mFrameworkInstallObserver = new AppDirObserver(
948 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
949 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700950 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
951 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700952 scanMode | SCAN_NO_DEX, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800953
954 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
956 mSystemInstallObserver = new AppDirObserver(
957 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
958 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700959 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700960 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800961
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700962 // Collect all vendor packages.
963 mVendorAppDir = new File("/vendor/app");
964 mVendorInstallObserver = new AppDirObserver(
965 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
966 mVendorInstallObserver.startWatching();
967 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700968 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700969
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800970 if (mInstaller != null) {
971 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
972 mInstaller.moveFiles();
973 }
974
975 // Prune any system packages that no longer exist.
976 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
977 while (psit.hasNext()) {
978 PackageSetting ps = psit.next();
979 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800980 && !mPackages.containsKey(ps.name)
981 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800982 psit.remove();
983 String msg = "System package " + ps.name
984 + " no longer exists; wiping its data";
985 reportSettingsProblem(Log.WARN, msg);
986 if (mInstaller != null) {
Amith Yamasani0b285492011-04-14 17:35:23 -0700987 mInstaller.remove(ps.name, 0);
988 mUserManager.removePackageForAllUsers(ps.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800989 }
990 }
991 }
992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 mAppInstallDir = new File(dataDir, "app");
994 if (mInstaller == null) {
995 // Make sure these dirs exist, when we are running in
996 // the simulator.
997 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
998 }
999 //look for any incomplete package installations
Kenny Root447106f2011-03-23 11:00:15 -07001000 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 //clean up list
1002 for(int i = 0; i < deletePkgsList.size(); i++) {
1003 //clean up here
1004 cleanupInstallFailedPackage(deletePkgsList.get(i));
1005 }
1006 //delete tmp files
1007 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001008
1009 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 SystemClock.uptimeMillis());
1011 mAppInstallObserver = new AppDirObserver(
1012 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1013 mAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001014 scanDirLI(mAppInstallDir, 0, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015
1016 mDrmAppInstallObserver = new AppDirObserver(
1017 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1018 mDrmAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001019 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1020 scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001022 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001024 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1026 + " seconds");
1027
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001028 // If the platform SDK has changed since the last time we booted,
1029 // we need to re-grant app permission to catch any new ones that
1030 // appear. This is really a hack, and means that apps can in some
1031 // cases get permissions that the user didn't initially explicitly
1032 // allow... it would be nice to have some better way to handle
1033 // this situation.
1034 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1035 != mSdkVersion;
1036 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1037 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1038 + "; regranting permissions for internal storage");
1039 mSettings.mInternalSdkPlatform = mSdkVersion;
1040
Kenny Root447106f2011-03-23 11:00:15 -07001041 updatePermissionsLPw(null, null, true, regrantPermissions, regrantPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042
Kenny Root447106f2011-03-23 11:00:15 -07001043 // can downgrade to reader
1044 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001046 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 // Now after opening every single application zip, make sure they
1050 // are all flushed. Not really needed, but keeps things nice and
1051 // tidy.
1052 Runtime.getRuntime().gc();
1053 } // synchronized (mPackages)
1054 } // synchronized (mInstallLock)
1055 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 @Override
1058 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1059 throws RemoteException {
1060 try {
1061 return super.onTransact(code, data, reply, flags);
1062 } catch (RuntimeException e) {
1063 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001064 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 }
1066 throw e;
1067 }
1068 }
1069
Dianne Hackborne6620b22010-01-22 14:46:21 -08001070 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001071 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 if (mInstaller != null) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001073 int retCode = mInstaller.remove(ps.name, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001075 Slog.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -08001076 + ps.name + ", retcode=" + retCode);
Amith Yamasani0b285492011-04-14 17:35:23 -07001077 } else {
1078 mUserManager.removePackageForAllUsers(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 }
1080 } else {
1081 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -08001082 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 File dataDir = new File(pkg.applicationInfo.dataDir);
1084 dataDir.delete();
1085 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001086 if (ps.codePath != null) {
1087 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001088 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001089 }
1090 }
1091 if (ps.resourcePath != null) {
1092 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001093 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001094 }
1095 }
Kenny Root447106f2011-03-23 11:00:15 -07001096 mSettings.removePackageLPw(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 }
1098
1099 void readPermissions() {
1100 // Read permissions from .../etc/permission directory.
1101 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1102 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001103 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 return;
1105 }
1106 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001107 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 return;
1109 }
1110
1111 // Iterate over the files in the directory and scan .xml files
1112 for (File f : libraryDir.listFiles()) {
1113 // We'll read platform.xml last
1114 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1115 continue;
1116 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001119 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 continue;
1121 }
1122 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001123 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 continue;
1125 }
1126
1127 readPermissionsFromXml(f);
1128 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1131 final File permFile = new File(Environment.getRootDirectory(),
1132 "etc/permissions/platform.xml");
1133 readPermissionsFromXml(permFile);
1134 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001135
1136 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 FileReader permReader = null;
1138 try {
1139 permReader = new FileReader(permFile);
1140 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001141 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 return;
1143 }
1144
1145 try {
1146 XmlPullParser parser = Xml.newPullParser();
1147 parser.setInput(permReader);
1148
1149 XmlUtils.beginDocument(parser, "permissions");
1150
1151 while (true) {
1152 XmlUtils.nextElement(parser);
1153 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1154 break;
1155 }
1156
1157 String name = parser.getName();
1158 if ("group".equals(name)) {
1159 String gidStr = parser.getAttributeValue(null, "gid");
1160 if (gidStr != null) {
1161 int gid = Integer.parseInt(gidStr);
1162 mGlobalGids = appendInt(mGlobalGids, gid);
1163 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001164 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 + parser.getPositionDescription());
1166 }
1167
1168 XmlUtils.skipCurrentTag(parser);
1169 continue;
1170 } else if ("permission".equals(name)) {
1171 String perm = parser.getAttributeValue(null, "name");
1172 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001173 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 + parser.getPositionDescription());
1175 XmlUtils.skipCurrentTag(parser);
1176 continue;
1177 }
1178 perm = perm.intern();
1179 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 } else if ("assign-permission".equals(name)) {
1182 String perm = parser.getAttributeValue(null, "name");
1183 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001184 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 + parser.getPositionDescription());
1186 XmlUtils.skipCurrentTag(parser);
1187 continue;
1188 }
1189 String uidStr = parser.getAttributeValue(null, "uid");
1190 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001191 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 + parser.getPositionDescription());
1193 XmlUtils.skipCurrentTag(parser);
1194 continue;
1195 }
1196 int uid = Process.getUidForName(uidStr);
1197 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001198 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 + uidStr + "\" at "
1200 + parser.getPositionDescription());
1201 XmlUtils.skipCurrentTag(parser);
1202 continue;
1203 }
1204 perm = perm.intern();
1205 HashSet<String> perms = mSystemPermissions.get(uid);
1206 if (perms == null) {
1207 perms = new HashSet<String>();
1208 mSystemPermissions.put(uid, perms);
1209 }
1210 perms.add(perm);
1211 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 } else if ("library".equals(name)) {
1214 String lname = parser.getAttributeValue(null, "name");
1215 String lfile = parser.getAttributeValue(null, "file");
1216 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001217 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 + parser.getPositionDescription());
1219 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001220 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 + parser.getPositionDescription());
1222 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001223 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001224 mSharedLibraries.put(lname, lfile);
1225 }
1226 XmlUtils.skipCurrentTag(parser);
1227 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001228
Dianne Hackborn49237342009-08-27 20:08:01 -07001229 } else if ("feature".equals(name)) {
1230 String fname = parser.getAttributeValue(null, "name");
1231 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001232 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001233 + parser.getPositionDescription());
1234 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001235 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001236 FeatureInfo fi = new FeatureInfo();
1237 fi.name = fname;
1238 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 XmlUtils.skipCurrentTag(parser);
1241 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 } else {
1244 XmlUtils.skipCurrentTag(parser);
1245 continue;
1246 }
1247
1248 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001249 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001251 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001253 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 }
1255 }
1256
1257 void readPermission(XmlPullParser parser, String name)
1258 throws IOException, XmlPullParserException {
1259
1260 name = name.intern();
1261
1262 BasePermission bp = mSettings.mPermissions.get(name);
1263 if (bp == null) {
1264 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1265 mSettings.mPermissions.put(name, bp);
1266 }
1267 int outerDepth = parser.getDepth();
1268 int type;
1269 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1270 && (type != XmlPullParser.END_TAG
1271 || parser.getDepth() > outerDepth)) {
1272 if (type == XmlPullParser.END_TAG
1273 || type == XmlPullParser.TEXT) {
1274 continue;
1275 }
1276
1277 String tagName = parser.getName();
1278 if ("group".equals(tagName)) {
1279 String gidStr = parser.getAttributeValue(null, "gid");
1280 if (gidStr != null) {
1281 int gid = Process.getGidForName(gidStr);
1282 bp.gids = appendInt(bp.gids, gid);
1283 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001284 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 + parser.getPositionDescription());
1286 }
1287 }
1288 XmlUtils.skipCurrentTag(parser);
1289 }
1290 }
1291
1292 static int[] appendInt(int[] cur, int val) {
1293 if (cur == null) {
1294 return new int[] { val };
1295 }
1296 final int N = cur.length;
1297 for (int i=0; i<N; i++) {
1298 if (cur[i] == val) {
1299 return cur;
1300 }
1301 }
1302 int[] ret = new int[N+1];
1303 System.arraycopy(cur, 0, ret, 0, N);
1304 ret[N] = val;
1305 return ret;
1306 }
1307
1308 static int[] appendInts(int[] cur, int[] add) {
1309 if (add == null) return cur;
1310 if (cur == null) return add;
1311 final int N = add.length;
1312 for (int i=0; i<N; i++) {
1313 cur = appendInt(cur, add[i]);
1314 }
1315 return cur;
1316 }
1317
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001318 static int[] removeInt(int[] cur, int val) {
1319 if (cur == null) {
1320 return null;
1321 }
1322 final int N = cur.length;
1323 for (int i=0; i<N; i++) {
1324 if (cur[i] == val) {
1325 int[] ret = new int[N-1];
1326 if (i > 0) {
1327 System.arraycopy(cur, 0, ret, 0, i);
1328 }
1329 if (i < (N-1)) {
Jeff Brown8c8bb8b2010-04-20 17:21:47 -07001330 System.arraycopy(cur, i + 1, ret, i, N - i - 1);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001331 }
1332 return ret;
1333 }
1334 }
1335 return cur;
1336 }
1337
1338 static int[] removeInts(int[] cur, int[] rem) {
1339 if (rem == null) return cur;
1340 if (cur == null) return cur;
1341 final int N = rem.length;
1342 for (int i=0; i<N; i++) {
1343 cur = removeInt(cur, rem[i]);
1344 }
1345 return cur;
1346 }
1347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001349 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1350 // The package has been uninstalled but has retained data and resources.
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001351 return PackageParser.generatePackageInfo(p, null, flags, 0, 0);
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 final PackageSetting ps = (PackageSetting)p.mExtras;
1354 if (ps == null) {
1355 return null;
1356 }
1357 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001358 return PackageParser.generatePackageInfo(p, gp.gids, flags,
1359 ps.firstInstallTime, ps.lastUpdateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
1361
1362 public PackageInfo getPackageInfo(String packageName, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001363 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 synchronized (mPackages) {
1365 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001366 if (DEBUG_PACKAGE_INFO)
1367 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 if (p != null) {
1369 return generatePackageInfo(p, flags);
1370 }
1371 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Kenny Root447106f2011-03-23 11:00:15 -07001372 return generatePackageInfoFromSettingsLPw(packageName, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374 }
1375 return null;
1376 }
1377
Dianne Hackborn47096932010-02-11 15:57:09 -08001378 public String[] currentToCanonicalPackageNames(String[] names) {
1379 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001380 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001381 synchronized (mPackages) {
1382 for (int i=names.length-1; i>=0; i--) {
1383 PackageSetting ps = mSettings.mPackages.get(names[i]);
1384 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1385 }
1386 }
1387 return out;
1388 }
1389
1390 public String[] canonicalToCurrentPackageNames(String[] names) {
1391 String[] out = new String[names.length];
Kenny Root447106f2011-03-23 11:00:15 -07001392 // reader
Dianne Hackborn47096932010-02-11 15:57:09 -08001393 synchronized (mPackages) {
1394 for (int i=names.length-1; i>=0; i--) {
1395 String cur = mSettings.mRenamedPackages.get(names[i]);
1396 out[i] = cur != null ? cur : names[i];
1397 }
1398 }
1399 return out;
1400 }
1401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 public int getPackageUid(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001403 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 synchronized (mPackages) {
1405 PackageParser.Package p = mPackages.get(packageName);
1406 if(p != null) {
1407 return p.applicationInfo.uid;
1408 }
1409 PackageSetting ps = mSettings.mPackages.get(packageName);
1410 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1411 return -1;
1412 }
1413 p = ps.pkg;
1414 return p != null ? p.applicationInfo.uid : -1;
1415 }
1416 }
1417
1418 public int[] getPackageGids(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07001419 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 synchronized (mPackages) {
1421 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001422 if (DEBUG_PACKAGE_INFO)
1423 Log.v(TAG, "getPackageGids" + packageName + ": " + p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 if (p != null) {
1425 final PackageSetting ps = (PackageSetting)p.mExtras;
1426 final SharedUserSetting suid = ps.sharedUser;
1427 return suid != null ? suid.gids : ps.gids;
1428 }
1429 }
1430 // stupid thing to indicate an error.
1431 return new int[0];
1432 }
1433
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001434 static final PermissionInfo generatePermissionInfo(
1435 BasePermission bp, int flags) {
1436 if (bp.perm != null) {
1437 return PackageParser.generatePermissionInfo(bp.perm, flags);
1438 }
1439 PermissionInfo pi = new PermissionInfo();
1440 pi.name = bp.name;
1441 pi.packageName = bp.sourcePackage;
1442 pi.nonLocalizedLabel = bp.name;
1443 pi.protectionLevel = bp.protectionLevel;
1444 return pi;
1445 }
1446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 public PermissionInfo getPermissionInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001448 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 synchronized (mPackages) {
1450 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001451 if (p != null) {
1452 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 }
1454 return null;
1455 }
1456 }
1457
1458 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001459 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 synchronized (mPackages) {
1461 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1462 for (BasePermission p : mSettings.mPermissions.values()) {
1463 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001464 if (p.perm == null || p.perm.info.group == null) {
1465 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001468 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1470 }
1471 }
1472 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 if (out.size() > 0) {
1475 return out;
1476 }
1477 return mPermissionGroups.containsKey(group) ? out : null;
1478 }
1479 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001482 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 synchronized (mPackages) {
1484 return PackageParser.generatePermissionGroupInfo(
1485 mPermissionGroups.get(name), flags);
1486 }
1487 }
1488
1489 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001490 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 synchronized (mPackages) {
1492 final int N = mPermissionGroups.size();
1493 ArrayList<PermissionGroupInfo> out
1494 = new ArrayList<PermissionGroupInfo>(N);
1495 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1496 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1497 }
1498 return out;
1499 }
1500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001501
Kenny Root447106f2011-03-23 11:00:15 -07001502 private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001504 if (ps != null) {
1505 if (ps.pkg == null) {
1506 PackageInfo pInfo = generatePackageInfoFromSettingsLPw(packageName, flags);
1507 if (pInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 return pInfo.applicationInfo;
1509 }
1510 return null;
1511 }
1512 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1513 }
1514 return null;
1515 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001516
Kenny Root447106f2011-03-23 11:00:15 -07001517 private PackageInfo generatePackageInfoFromSettingsLPw(String packageName, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 PackageSetting ps = mSettings.mPackages.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07001519 if (ps != null) {
1520 if (ps.pkg == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 ps.pkg = new PackageParser.Package(packageName);
1522 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001523 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1524 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1525 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
Amith Yamasani0b285492011-04-14 17:35:23 -07001526 ps.pkg.applicationInfo.dataDir =
1527 getDataPathForPackage(ps.pkg.packageName, 0).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001528 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07001529 ps.pkg.mSetEnabled = ps.enabled;
Dianne Hackborne7f97212011-02-24 14:40:20 -08001530 ps.pkg.mSetStopped = ps.stopped;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 return generatePackageInfo(ps.pkg, flags);
1533 }
1534 return null;
1535 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07001538 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 synchronized (mPackages) {
1540 PackageParser.Package p = mPackages.get(packageName);
Kenny Root9718cf52011-02-23 16:45:26 -08001541 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 TAG, "getApplicationInfo " + packageName
1543 + ": " + p);
1544 if (p != null) {
1545 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001546 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 }
1548 if ("android".equals(packageName)||"system".equals(packageName)) {
1549 return mAndroidApplication;
1550 }
1551 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Kenny Root447106f2011-03-23 11:00:15 -07001552 return generateApplicationInfoFromSettingsLPw(packageName, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
1554 }
1555 return null;
1556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001557
1558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1560 mContext.enforceCallingOrSelfPermission(
1561 android.Manifest.permission.CLEAR_APP_CACHE, null);
1562 // Queue up an async operation since clearing cache may take a little while.
1563 mHandler.post(new Runnable() {
1564 public void run() {
1565 mHandler.removeCallbacks(this);
1566 int retCode = -1;
1567 if (mInstaller != null) {
1568 retCode = mInstaller.freeCache(freeStorageSize);
1569 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001570 Slog.w(TAG, "Couldn't clear application caches");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 }
1572 } //end if mInstaller
1573 if (observer != null) {
1574 try {
1575 observer.onRemoveCompleted(null, (retCode >= 0));
1576 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001577 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 }
1579 }
1580 }
1581 });
1582 }
1583
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001584 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001585 mContext.enforceCallingOrSelfPermission(
1586 android.Manifest.permission.CLEAR_APP_CACHE, null);
1587 // Queue up an async operation since clearing cache may take a little while.
1588 mHandler.post(new Runnable() {
1589 public void run() {
1590 mHandler.removeCallbacks(this);
1591 int retCode = -1;
1592 if (mInstaller != null) {
1593 retCode = mInstaller.freeCache(freeStorageSize);
1594 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001595 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001596 }
1597 }
1598 if(pi != null) {
1599 try {
1600 // Callback via pending intent
1601 int code = (retCode >= 0) ? 1 : 0;
1602 pi.sendIntent(null, code, null,
1603 null, null);
1604 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001605 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001606 }
1607 }
1608 }
1609 });
1610 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1613 synchronized (mPackages) {
1614 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001615
Kenny Root9718cf52011-02-23 16:45:26 -08001616 if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
Kenny Root447106f2011-03-23 11:00:15 -07001617 if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001618 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 }
1620 if (mResolveComponentName.equals(component)) {
1621 return mResolveActivity;
1622 }
1623 }
1624 return null;
1625 }
1626
1627 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1628 synchronized (mPackages) {
1629 PackageParser.Activity a = mReceivers.mActivities.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001630 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 TAG, "getReceiverInfo " + component + ": " + a);
Kenny Root447106f2011-03-23 11:00:15 -07001632 if (a != null && mSettings.isEnabledLPr(a.info, flags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 return PackageParser.generateActivityInfo(a, flags);
1634 }
1635 }
1636 return null;
1637 }
1638
1639 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1640 synchronized (mPackages) {
1641 PackageParser.Service s = mServices.mServices.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001642 if (DEBUG_PACKAGE_INFO) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 TAG, "getServiceInfo " + component + ": " + s);
Kenny Root447106f2011-03-23 11:00:15 -07001644 if (s != null && mSettings.isEnabledLPr(s.info, flags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 return PackageParser.generateServiceInfo(s, flags);
1646 }
1647 }
1648 return null;
1649 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001650
Dianne Hackborn361199b2010-08-30 17:42:07 -07001651 public ProviderInfo getProviderInfo(ComponentName component, int flags) {
1652 synchronized (mPackages) {
1653 PackageParser.Provider p = mProvidersByComponent.get(component);
Kenny Root9718cf52011-02-23 16:45:26 -08001654 if (DEBUG_PACKAGE_INFO) Log.v(
Dianne Hackborn361199b2010-08-30 17:42:07 -07001655 TAG, "getProviderInfo " + component + ": " + p);
Kenny Root447106f2011-03-23 11:00:15 -07001656 if (p != null && mSettings.isEnabledLPr(p.info, flags)) {
Dianne Hackborn361199b2010-08-30 17:42:07 -07001657 return PackageParser.generateProviderInfo(p, flags);
1658 }
1659 }
1660 return null;
1661 }
1662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 public String[] getSystemSharedLibraryNames() {
1664 Set<String> libSet;
1665 synchronized (mPackages) {
1666 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001667 int size = libSet.size();
1668 if (size > 0) {
1669 String[] libs = new String[size];
1670 libSet.toArray(libs);
1671 return libs;
1672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001674 return null;
1675 }
1676
1677 public FeatureInfo[] getSystemAvailableFeatures() {
1678 Collection<FeatureInfo> featSet;
1679 synchronized (mPackages) {
1680 featSet = mAvailableFeatures.values();
1681 int size = featSet.size();
1682 if (size > 0) {
1683 FeatureInfo[] features = new FeatureInfo[size+1];
1684 featSet.toArray(features);
1685 FeatureInfo fi = new FeatureInfo();
1686 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1687 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1688 features[size] = fi;
1689 return features;
1690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
1692 return null;
1693 }
1694
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001695 public boolean hasSystemFeature(String name) {
1696 synchronized (mPackages) {
1697 return mAvailableFeatures.containsKey(name);
1698 }
1699 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 public int checkPermission(String permName, String pkgName) {
1702 synchronized (mPackages) {
1703 PackageParser.Package p = mPackages.get(pkgName);
1704 if (p != null && p.mExtras != null) {
1705 PackageSetting ps = (PackageSetting)p.mExtras;
1706 if (ps.sharedUser != null) {
1707 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1708 return PackageManager.PERMISSION_GRANTED;
1709 }
1710 } else if (ps.grantedPermissions.contains(permName)) {
1711 return PackageManager.PERMISSION_GRANTED;
1712 }
1713 }
1714 }
1715 return PackageManager.PERMISSION_DENIED;
1716 }
1717
1718 public int checkUidPermission(String permName, int uid) {
1719 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07001720 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001722 GrantedPermissions gp = (GrantedPermissions)obj;
1723 if (gp.grantedPermissions.contains(permName)) {
1724 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 }
1726 } else {
1727 HashSet<String> perms = mSystemPermissions.get(uid);
1728 if (perms != null && perms.contains(permName)) {
1729 return PackageManager.PERMISSION_GRANTED;
1730 }
1731 }
1732 }
1733 return PackageManager.PERMISSION_DENIED;
1734 }
1735
1736 private BasePermission findPermissionTreeLP(String permName) {
1737 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1738 if (permName.startsWith(bp.name) &&
1739 permName.length() > bp.name.length() &&
1740 permName.charAt(bp.name.length()) == '.') {
1741 return bp;
1742 }
1743 }
1744 return null;
1745 }
1746
1747 private BasePermission checkPermissionTreeLP(String permName) {
1748 if (permName != null) {
1749 BasePermission bp = findPermissionTreeLP(permName);
1750 if (bp != null) {
1751 if (bp.uid == Binder.getCallingUid()) {
1752 return bp;
1753 }
1754 throw new SecurityException("Calling uid "
1755 + Binder.getCallingUid()
1756 + " is not allowed to add to permission tree "
1757 + bp.name + " owned by uid " + bp.uid);
1758 }
1759 }
1760 throw new SecurityException("No permission tree found for " + permName);
1761 }
1762
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001763 static boolean compareStrings(CharSequence s1, CharSequence s2) {
1764 if (s1 == null) {
1765 return s2 == null;
1766 }
1767 if (s2 == null) {
1768 return false;
1769 }
1770 if (s1.getClass() != s2.getClass()) {
1771 return false;
1772 }
1773 return s1.equals(s2);
1774 }
1775
1776 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
1777 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07001778 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001779 if (pi1.protectionLevel != pi2.protectionLevel) return false;
1780 if (!compareStrings(pi1.name, pi2.name)) return false;
1781 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
1782 // We'll take care of setting this one.
1783 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
1784 // These are not currently stored in settings.
1785 //if (!compareStrings(pi1.group, pi2.group)) return false;
1786 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
1787 //if (pi1.labelRes != pi2.labelRes) return false;
1788 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
1789 return true;
1790 }
1791
1792 boolean addPermissionLocked(PermissionInfo info, boolean async) {
1793 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1794 throw new SecurityException("Label must be specified in permission");
1795 }
1796 BasePermission tree = checkPermissionTreeLP(info.name);
1797 BasePermission bp = mSettings.mPermissions.get(info.name);
1798 boolean added = bp == null;
1799 boolean changed = true;
1800 if (added) {
1801 bp = new BasePermission(info.name, tree.sourcePackage,
1802 BasePermission.TYPE_DYNAMIC);
1803 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1804 throw new SecurityException(
1805 "Not allowed to modify non-dynamic permission "
1806 + info.name);
1807 } else {
1808 if (bp.protectionLevel == info.protectionLevel
1809 && bp.perm.owner.equals(tree.perm.owner)
1810 && bp.uid == tree.uid
1811 && comparePermissionInfos(bp.perm.info, info)) {
1812 changed = false;
1813 }
1814 }
1815 bp.protectionLevel = info.protectionLevel;
1816 bp.perm = new PackageParser.Permission(tree.perm.owner,
1817 new PermissionInfo(info));
1818 bp.perm.info.packageName = tree.perm.info.packageName;
1819 bp.uid = tree.uid;
1820 if (added) {
1821 mSettings.mPermissions.put(info.name, bp);
1822 }
1823 if (changed) {
1824 if (!async) {
Kenny Root447106f2011-03-23 11:00:15 -07001825 mSettings.writeLPr();
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001826 } else {
1827 scheduleWriteSettingsLocked();
1828 }
1829 }
1830 return added;
1831 }
1832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 public boolean addPermission(PermissionInfo info) {
1834 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001835 return addPermissionLocked(info, false);
1836 }
1837 }
1838
1839 public boolean addPermissionAsync(PermissionInfo info) {
1840 synchronized (mPackages) {
1841 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 }
1843 }
1844
1845 public void removePermission(String name) {
1846 synchronized (mPackages) {
1847 checkPermissionTreeLP(name);
1848 BasePermission bp = mSettings.mPermissions.get(name);
1849 if (bp != null) {
1850 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1851 throw new SecurityException(
1852 "Not allowed to modify non-dynamic permission "
1853 + name);
1854 }
1855 mSettings.mPermissions.remove(name);
Kenny Root447106f2011-03-23 11:00:15 -07001856 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 }
1858 }
1859 }
1860
Dianne Hackborn854060af2009-07-09 18:14:31 -07001861 public boolean isProtectedBroadcast(String actionName) {
1862 synchronized (mPackages) {
1863 return mProtectedBroadcasts.contains(actionName);
1864 }
1865 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 public int checkSignatures(String pkg1, String pkg2) {
1868 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07001869 final PackageParser.Package p1 = mPackages.get(pkg1);
1870 final PackageParser.Package p2 = mPackages.get(pkg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 if (p1 == null || p1.mExtras == null
1872 || p2 == null || p2.mExtras == null) {
1873 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1874 }
Kenny Root447106f2011-03-23 11:00:15 -07001875 return compareSignatures(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876 }
1877 }
1878
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001879 public int checkUidSignatures(int uid1, int uid2) {
Kenny Root447106f2011-03-23 11:00:15 -07001880 // reader
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001881 synchronized (mPackages) {
1882 Signature[] s1;
1883 Signature[] s2;
Kenny Root447106f2011-03-23 11:00:15 -07001884 Object obj = mSettings.getUserIdLPr(uid1);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001885 if (obj != null) {
1886 if (obj instanceof SharedUserSetting) {
1887 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1888 } else if (obj instanceof PackageSetting) {
1889 s1 = ((PackageSetting)obj).signatures.mSignatures;
1890 } else {
1891 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1892 }
1893 } else {
1894 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1895 }
Kenny Root447106f2011-03-23 11:00:15 -07001896 obj = mSettings.getUserIdLPr(uid2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001897 if (obj != null) {
1898 if (obj instanceof SharedUserSetting) {
1899 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1900 } else if (obj instanceof PackageSetting) {
1901 s2 = ((PackageSetting)obj).signatures.mSignatures;
1902 } else {
1903 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1904 }
1905 } else {
1906 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1907 }
Kenny Root447106f2011-03-23 11:00:15 -07001908 return compareSignatures(s1, s2);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001909 }
1910 }
1911
Kenny Root447106f2011-03-23 11:00:15 -07001912 static int compareSignatures(Signature[] s1, Signature[] s2) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001913 if (s1 == null) {
1914 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1916 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1917 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001918 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1920 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001921 HashSet<Signature> set1 = new HashSet<Signature>();
1922 for (Signature sig : s1) {
1923 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001925 HashSet<Signature> set2 = new HashSet<Signature>();
1926 for (Signature sig : s2) {
1927 set2.add(sig);
1928 }
1929 // Make sure s2 contains all signatures in s1.
1930 if (set1.equals(set2)) {
1931 return PackageManager.SIGNATURE_MATCH;
1932 }
1933 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 }
1935
1936 public String[] getPackagesForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07001937 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07001939 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07001941 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 final int N = sus.packages.size();
Kenny Root447106f2011-03-23 11:00:15 -07001943 final String[] res = new String[N];
1944 final Iterator<PackageSetting> it = sus.packages.iterator();
1945 int i = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 while (it.hasNext()) {
1947 res[i++] = it.next().name;
1948 }
1949 return res;
1950 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07001951 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 return new String[] { ps.name };
1953 }
1954 }
1955 return null;
1956 }
1957
1958 public String getNameForUid(int uid) {
Kenny Root447106f2011-03-23 11:00:15 -07001959 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07001961 Object obj = mSettings.getUserIdLPr(uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 if (obj instanceof SharedUserSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07001963 final SharedUserSetting sus = (SharedUserSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 return sus.name + ":" + sus.userId;
1965 } else if (obj instanceof PackageSetting) {
Kenny Root447106f2011-03-23 11:00:15 -07001966 final PackageSetting ps = (PackageSetting) obj;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 return ps.name;
1968 }
1969 }
1970 return null;
1971 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 public int getUidForSharedUser(String sharedUserName) {
1974 if(sharedUserName == null) {
1975 return -1;
1976 }
Kenny Root447106f2011-03-23 11:00:15 -07001977 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001978 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07001979 final SharedUserSetting suid = mSettings.getSharedUserLPw(sharedUserName, 0, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 if(suid == null) {
1981 return -1;
1982 }
1983 return suid.userId;
1984 }
1985 }
1986
1987 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1988 int flags) {
1989 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001990 return chooseBestActivity(intent, resolvedType, flags, query);
1991 }
1992
Mihai Predaeae850c2009-05-13 10:13:48 +02001993 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1994 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 if (query != null) {
1996 final int N = query.size();
1997 if (N == 1) {
1998 return query.get(0);
1999 } else if (N > 1) {
2000 // If there is more than one activity with the same priority,
2001 // then let the user decide between them.
2002 ResolveInfo r0 = query.get(0);
2003 ResolveInfo r1 = query.get(1);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002004 if (DEBUG_INTENT_MATCHING) {
2005 Log.d(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
2006 + r1.activityInfo.name + "=" + r1.priority);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 }
2008 // If the first activity has a higher priority, or a different
2009 // default, then it is always desireable to pick it.
2010 if (r0.priority != r1.priority
2011 || r0.preferredOrder != r1.preferredOrder
2012 || r0.isDefault != r1.isDefault) {
2013 return query.get(0);
2014 }
2015 // If we have saved a preference for a preferred activity for
2016 // this Intent, use that.
2017 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
2018 flags, query, r0.priority);
2019 if (ri != null) {
2020 return ri;
2021 }
2022 return mResolveInfo;
2023 }
2024 }
2025 return null;
2026 }
2027
2028 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
2029 int flags, List<ResolveInfo> query, int priority) {
Kenny Root447106f2011-03-23 11:00:15 -07002030 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 synchronized (mPackages) {
2032 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2033 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002034 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2036 if (prefs != null && prefs.size() > 0) {
2037 // First figure out how good the original match set is.
2038 // We will only allow preferred activities that came
2039 // from the same match quality.
2040 int match = 0;
Kenny Root447106f2011-03-23 11:00:15 -07002041
2042 if (DEBUG_PREFERRED) {
2043 Log.v(TAG, "Figuring out best match...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 }
Kenny Root447106f2011-03-23 11:00:15 -07002045
2046 final int N = query.size();
2047 for (int j=0; j<N; j++) {
2048 final ResolveInfo ri = query.get(j);
2049 if (DEBUG_PREFERRED) {
2050 Log.v(TAG, "Match for " + ri.activityInfo + ": 0x"
2051 + Integer.toHexString(match));
2052 }
2053 if (ri.match > match) {
2054 match = ri.match;
2055 }
2056 }
2057
2058 if (DEBUG_PREFERRED) {
2059 Log.v(TAG, "Best match: 0x" + Integer.toHexString(match));
2060 }
2061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 match &= IntentFilter.MATCH_CATEGORY_MASK;
2063 final int M = prefs.size();
2064 for (int i=0; i<M; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002065 final PreferredActivity pa = prefs.get(i);
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002066 if (pa.mPref.mMatch != match) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 continue;
2068 }
Kenny Root447106f2011-03-23 11:00:15 -07002069 final ActivityInfo ai = getActivityInfo(pa.mPref.mComponent, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 if (DEBUG_PREFERRED) {
2071 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002072 if (ai != null) {
2073 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2074 } else {
2075 Log.v(TAG, " null");
2076 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 }
2078 if (ai != null) {
2079 for (int j=0; j<N; j++) {
Kenny Root447106f2011-03-23 11:00:15 -07002080 final ResolveInfo ri = query.get(j);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 if (!ri.activityInfo.applicationInfo.packageName
2082 .equals(ai.applicationInfo.packageName)) {
2083 continue;
2084 }
2085 if (!ri.activityInfo.name.equals(ai.name)) {
2086 continue;
2087 }
2088
2089 // Okay we found a previously set preferred app.
2090 // If the result set is different from when this
2091 // was created, we need to clear it and re-ask the
2092 // user their preference.
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08002093 if (!pa.mPref.sameSet(query, priority)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002094 Slog.i(TAG, "Result set changed, dropping preferred activity for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 + intent + " type " + resolvedType);
2096 mSettings.mPreferredActivities.removeFilter(pa);
2097 return null;
2098 }
2099
2100 // Yay!
2101 return ri;
2102 }
2103 }
2104 }
2105 }
2106 }
2107 return null;
2108 }
2109
2110 public List<ResolveInfo> queryIntentActivities(Intent intent,
2111 String resolvedType, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002112 final ComponentName comp = intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002114 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2115 final ActivityInfo ai = getActivityInfo(comp, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 if (ai != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002117 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 ri.activityInfo = ai;
2119 list.add(ri);
2120 }
2121 return list;
2122 }
2123
Kenny Root447106f2011-03-23 11:00:15 -07002124 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002126 final String pkgName = intent.getPackage();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002127 if (pkgName == null) {
Kenny Root447106f2011-03-23 11:00:15 -07002128 return mActivities.queryIntent(intent, resolvedType, flags);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002129 }
Kenny Root447106f2011-03-23 11:00:15 -07002130 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002131 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002132 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
2133 pkg.activities);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002134 }
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08002135 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 }
2137 }
2138
2139 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2140 Intent[] specifics, String[] specificTypes, Intent intent,
2141 String resolvedType, int flags) {
2142 final String resultsAction = intent.getAction();
2143
Kenny Root447106f2011-03-23 11:00:15 -07002144 List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
2145 | PackageManager.GET_RESOLVED_FILTER);
2146
2147 if (DEBUG_INTENT_MATCHING) {
2148 Log.v(TAG, "Query " + intent + ": " + results);
2149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150
2151 int specificsPos = 0;
2152 int N;
2153
2154 // todo: note that the algorithm used here is O(N^2). This
2155 // isn't a problem in our current environment, but if we start running
2156 // into situations where we have more than 5 or 10 matches then this
2157 // should probably be changed to something smarter...
2158
2159 // First we go through and resolve each of the specific items
2160 // that were supplied, taking care of removing any corresponding
2161 // duplicate items in the generic resolve list.
2162 if (specifics != null) {
2163 for (int i=0; i<specifics.length; i++) {
2164 final Intent sintent = specifics[i];
2165 if (sintent == null) {
2166 continue;
2167 }
2168
Kenny Root447106f2011-03-23 11:00:15 -07002169 if (DEBUG_INTENT_MATCHING) {
2170 Log.v(TAG, "Specific #" + i + ": " + sintent);
2171 }
2172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 String action = sintent.getAction();
2174 if (resultsAction != null && resultsAction.equals(action)) {
2175 // If this action was explicitly requested, then don't
2176 // remove things that have it.
2177 action = null;
2178 }
Kenny Root447106f2011-03-23 11:00:15 -07002179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 ResolveInfo ri = null;
2181 ActivityInfo ai = null;
Kenny Root447106f2011-03-23 11:00:15 -07002182
2183 ComponentName comp = sintent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 if (comp == null) {
2185 ri = resolveIntent(
2186 sintent,
2187 specificTypes != null ? specificTypes[i] : null,
2188 flags);
2189 if (ri == null) {
2190 continue;
2191 }
2192 if (ri == mResolveInfo) {
2193 // ACK! Must do something better with this.
2194 }
2195 ai = ri.activityInfo;
2196 comp = new ComponentName(ai.applicationInfo.packageName,
2197 ai.name);
2198 } else {
2199 ai = getActivityInfo(comp, flags);
2200 if (ai == null) {
2201 continue;
2202 }
2203 }
2204
2205 // Look for any generic query activities that are duplicates
2206 // of this specific one, and remove them from the results.
Kenny Root9718cf52011-02-23 16:45:26 -08002207 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Specific #" + i + ": " + ai);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 N = results.size();
2209 int j;
2210 for (j=specificsPos; j<N; j++) {
2211 ResolveInfo sri = results.get(j);
2212 if ((sri.activityInfo.name.equals(comp.getClassName())
2213 && sri.activityInfo.applicationInfo.packageName.equals(
2214 comp.getPackageName()))
2215 || (action != null && sri.filter.matchAction(action))) {
2216 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002217 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 TAG, "Removing duplicate item from " + j
2219 + " due to specific " + specificsPos);
2220 if (ri == null) {
2221 ri = sri;
2222 }
2223 j--;
2224 N--;
2225 }
2226 }
2227
2228 // Add this specific item to its proper place.
2229 if (ri == null) {
2230 ri = new ResolveInfo();
2231 ri.activityInfo = ai;
2232 }
2233 results.add(specificsPos, ri);
2234 ri.specificIndex = i;
2235 specificsPos++;
2236 }
2237 }
2238
2239 // Now we go through the remaining generic results and remove any
2240 // duplicate actions that are found here.
2241 N = results.size();
2242 for (int i=specificsPos; i<N-1; i++) {
2243 final ResolveInfo rii = results.get(i);
2244 if (rii.filter == null) {
2245 continue;
2246 }
2247
2248 // Iterate over all of the actions of this result's intent
2249 // filter... typically this should be just one.
2250 final Iterator<String> it = rii.filter.actionsIterator();
2251 if (it == null) {
2252 continue;
2253 }
2254 while (it.hasNext()) {
2255 final String action = it.next();
2256 if (resultsAction != null && resultsAction.equals(action)) {
2257 // If this action was explicitly requested, then don't
2258 // remove things that have it.
2259 continue;
2260 }
2261 for (int j=i+1; j<N; j++) {
2262 final ResolveInfo rij = results.get(j);
2263 if (rij.filter != null && rij.filter.hasAction(action)) {
2264 results.remove(j);
Kenny Root9718cf52011-02-23 16:45:26 -08002265 if (DEBUG_INTENT_MATCHING) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 TAG, "Removing duplicate item from " + j
2267 + " due to action " + action + " at " + i);
2268 j--;
2269 N--;
2270 }
2271 }
2272 }
2273
2274 // If the caller didn't request filter information, drop it now
2275 // so we don't have to marshall/unmarshall it.
2276 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2277 rii.filter = null;
2278 }
2279 }
2280
2281 // Filter out the caller activity if so requested.
2282 if (caller != null) {
2283 N = results.size();
2284 for (int i=0; i<N; i++) {
2285 ActivityInfo ainfo = results.get(i).activityInfo;
2286 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2287 && caller.getClassName().equals(ainfo.name)) {
2288 results.remove(i);
2289 break;
2290 }
2291 }
2292 }
2293
2294 // If the caller didn't request filter information,
2295 // drop them now so we don't have to
2296 // marshall/unmarshall it.
2297 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2298 N = results.size();
2299 for (int i=0; i<N; i++) {
2300 results.get(i).filter = null;
2301 }
2302 }
2303
Kenny Root9718cf52011-02-23 16:45:26 -08002304 if (DEBUG_INTENT_MATCHING) Log.v(TAG, "Result: " + results);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 return results;
2306 }
2307
Kenny Root447106f2011-03-23 11:00:15 -07002308 public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002309 ComponentName comp = intent.getComponent();
2310 if (comp != null) {
2311 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2312 ActivityInfo ai = getReceiverInfo(comp, flags);
2313 if (ai != null) {
2314 ResolveInfo ri = new ResolveInfo();
2315 ri.activityInfo = ai;
2316 list.add(ri);
2317 }
2318 return list;
2319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002320
Kenny Root447106f2011-03-23 11:00:15 -07002321 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002322 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002323 String pkgName = intent.getPackage();
2324 if (pkgName == null) {
Kenny Root447106f2011-03-23 11:00:15 -07002325 return mReceivers.queryIntent(intent, resolvedType, flags);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002326 }
Kenny Root447106f2011-03-23 11:00:15 -07002327 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002328 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002329 return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002330 }
2331 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 }
2333 }
2334
Kenny Root447106f2011-03-23 11:00:15 -07002335 public ResolveInfo resolveService(Intent intent, String resolvedType, int flags) {
2336 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 if (query != null) {
2338 if (query.size() >= 1) {
2339 // If there is more than one service with the same priority,
2340 // just arbitrarily pick the first one.
2341 return query.get(0);
2342 }
2343 }
2344 return null;
2345 }
2346
Kenny Root447106f2011-03-23 11:00:15 -07002347 public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags) {
2348 final ComponentName comp = intent.getComponent();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 if (comp != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002350 final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2351 final ServiceInfo si = getServiceInfo(comp, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 if (si != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002353 final ResolveInfo ri = new ResolveInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 ri.serviceInfo = si;
2355 list.add(ri);
2356 }
2357 return list;
2358 }
2359
Kenny Root447106f2011-03-23 11:00:15 -07002360 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 synchronized (mPackages) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002362 String pkgName = intent.getPackage();
2363 if (pkgName == null) {
Kenny Root447106f2011-03-23 11:00:15 -07002364 return mServices.queryIntent(intent, resolvedType, flags);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002365 }
Kenny Root447106f2011-03-23 11:00:15 -07002366 final PackageParser.Package pkg = mPackages.get(pkgName);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002367 if (pkg != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002368 return mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07002369 }
2370 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 }
2372 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 public List<PackageInfo> getInstalledPackages(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002375 final ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376
Kenny Root447106f2011-03-23 11:00:15 -07002377 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002378 synchronized (mPackages) {
2379 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Kenny Root447106f2011-03-23 11:00:15 -07002380 final Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002381 while (i.hasNext()) {
2382 final PackageSetting ps = i.next();
Kenny Root447106f2011-03-23 11:00:15 -07002383 final PackageInfo psPkg = generatePackageInfoFromSettingsLPw(ps.name, flags);
2384 if (psPkg != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 finalList.add(psPkg);
2386 }
2387 }
Kenny Root447106f2011-03-23 11:00:15 -07002388 } else {
2389 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 while (i.hasNext()) {
2391 final PackageParser.Package p = i.next();
2392 if (p.applicationInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002393 final PackageInfo pi = generatePackageInfo(p, flags);
2394 if (pi != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002395 finalList.add(pi);
2396 }
2397 }
2398 }
2399 }
2400 }
2401 return finalList;
2402 }
2403
2404 public List<ApplicationInfo> getInstalledApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002405 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2406 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 synchronized(mPackages) {
2408 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
Kenny Root447106f2011-03-23 11:00:15 -07002409 final Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 while (i.hasNext()) {
2411 final PackageSetting ps = i.next();
Kenny Root447106f2011-03-23 11:00:15 -07002412 ApplicationInfo ai = generateApplicationInfoFromSettingsLPw(ps.name, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 if(ai != null) {
2414 finalList.add(ai);
2415 }
2416 }
Kenny Root447106f2011-03-23 11:00:15 -07002417 } else {
2418 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 while (i.hasNext()) {
2420 final PackageParser.Package p = i.next();
2421 if (p.applicationInfo != null) {
2422 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2423 if(ai != null) {
2424 finalList.add(ai);
2425 }
2426 }
2427 }
2428 }
2429 }
2430 return finalList;
2431 }
2432
2433 public List<ApplicationInfo> getPersistentApplications(int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002434 final ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435
Kenny Root447106f2011-03-23 11:00:15 -07002436 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002437 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002438 final Iterator<PackageParser.Package> i = mPackages.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002439 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002440 final PackageParser.Package p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002441 if (p.applicationInfo != null
2442 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002443 && (!mSafeMode || isSystemApp(p))) {
Jey2eebf5c2009-11-18 18:37:31 -08002444 finalList.add(PackageParser.generateApplicationInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446 }
2447 }
2448
2449 return finalList;
2450 }
2451
2452 public ProviderInfo resolveContentProvider(String name, int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002453 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 synchronized (mPackages) {
2455 final PackageParser.Provider provider = mProviders.get(name);
2456 return provider != null
Kenny Root447106f2011-03-23 11:00:15 -07002457 && mSettings.isEnabledLPr(provider.info, flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 && (!mSafeMode || (provider.info.applicationInfo.flags
2459 &ApplicationInfo.FLAG_SYSTEM) != 0)
2460 ? PackageParser.generateProviderInfo(provider, flags)
2461 : null;
2462 }
2463 }
2464
Fred Quintana718d8a22009-04-29 17:53:20 -07002465 /**
2466 * @deprecated
2467 */
Kenny Root60f7ad82011-03-22 12:49:06 -07002468 @Deprecated
2469 public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07002470 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002472 final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
2473 .iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474
2475 while (i.hasNext()) {
2476 Map.Entry<String, PackageParser.Provider> entry = i.next();
2477 PackageParser.Provider p = entry.getValue();
2478
2479 if (p.syncable
2480 && (!mSafeMode || (p.info.applicationInfo.flags
2481 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2482 outNames.add(entry.getKey());
2483 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2484 }
2485 }
2486 }
2487 }
2488
2489 public List<ProviderInfo> queryContentProviders(String processName,
2490 int uid, int flags) {
2491 ArrayList<ProviderInfo> finalList = null;
2492
Kenny Root447106f2011-03-23 11:00:15 -07002493 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002495 final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002497 final PackageParser.Provider p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 if (p.info.authority != null
Kenny Root447106f2011-03-23 11:00:15 -07002499 && (processName == null
2500 || (p.info.processName.equals(processName)
2501 && p.info.applicationInfo.uid == uid))
2502 && mSettings.isEnabledLPr(p.info, flags)
2503 && (!mSafeMode
2504 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 if (finalList == null) {
2506 finalList = new ArrayList<ProviderInfo>(3);
2507 }
Kenny Root447106f2011-03-23 11:00:15 -07002508 finalList.add(PackageParser.generateProviderInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 }
2510 }
2511 }
2512
2513 if (finalList != null) {
2514 Collections.sort(finalList, mProviderInitOrderSorter);
2515 }
2516
2517 return finalList;
2518 }
2519
2520 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2521 int flags) {
Kenny Root447106f2011-03-23 11:00:15 -07002522 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 synchronized (mPackages) {
2524 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2525 return PackageParser.generateInstrumentationInfo(i, flags);
2526 }
2527 }
2528
2529 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2530 int flags) {
2531 ArrayList<InstrumentationInfo> finalList =
2532 new ArrayList<InstrumentationInfo>();
2533
Kenny Root447106f2011-03-23 11:00:15 -07002534 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07002536 final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 while (i.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07002538 final PackageParser.Instrumentation p = i.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 if (targetPackage == null
2540 || targetPackage.equals(p.info.targetPackage)) {
2541 finalList.add(PackageParser.generateInstrumentationInfo(p,
2542 flags));
2543 }
2544 }
2545 }
2546
2547 return finalList;
2548 }
2549
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002550 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07002552 if (files == null) {
2553 Log.d(TAG, "No files in app dir " + dir);
2554 return;
2555 }
2556
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002557 if (DEBUG_PACKAGE_SCANNING) {
Joe Onorato431bb222010-10-18 19:13:23 -04002558 Log.d(TAG, "Scanning app dir " + dir);
2559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560
2561 int i;
2562 for (i=0; i<files.length; i++) {
2563 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002564 if (!isPackageFilename(files[i])) {
2565 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002566 continue;
2567 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002568 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002569 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002570 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002571 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2572 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002573 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002574 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002575 file.delete();
2576 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 }
2578 }
2579
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002580 private static File getSettingsProblemFile() {
2581 File dataDir = Environment.getDataDirectory();
2582 File systemDir = new File(dataDir, "system");
2583 File fname = new File(systemDir, "uiderrors.txt");
2584 return fname;
2585 }
2586
Kenny Rootcf0b38c2011-03-22 14:17:59 -07002587 static void reportSettingsProblem(int priority, String msg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002589 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002590 FileOutputStream out = new FileOutputStream(fname, true);
2591 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002592 SimpleDateFormat formatter = new SimpleDateFormat();
2593 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2594 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 pw.close();
2596 FileUtils.setPermissions(
2597 fname.toString(),
2598 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2599 -1, -1);
2600 } catch (java.io.IOException e) {
2601 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002602 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 }
2604
2605 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2606 PackageParser.Package pkg, File srcFile, int parseFlags) {
2607 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07002608 if (ps != null
2609 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07002610 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07002611 if (ps.signatures.mSignatures != null
2612 && ps.signatures.mSignatures.length != 0) {
2613 // Optimization: reuse the existing cached certificates
2614 // if the package appears to be unchanged.
2615 pkg.mSignatures = ps.signatures.mSignatures;
2616 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002617 }
Jeff Browne7600722010-04-07 18:28:23 -07002618
2619 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002620 } else {
Jeff Browne7600722010-04-07 18:28:23 -07002621 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2622 }
2623
2624 if (!pp.collectCertificates(pkg, parseFlags)) {
2625 mLastScanError = pp.getParseError();
2626 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 }
2628 }
2629 return true;
2630 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 /*
2633 * Scan a package and return the newly parsed package.
2634 * Returns null in case of errors and the error code is stored in mLastScanError
2635 */
2636 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002637 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002639 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002641 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002644 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 if (pkg == null) {
2646 mLastScanError = pp.getParseError();
2647 return null;
2648 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002649 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 PackageSetting updatedPkg;
Kenny Root447106f2011-03-23 11:00:15 -07002651 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002653 // Look to see if we already know about this package.
2654 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002655 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002656 // This package has been renamed to its original name. Let's
2657 // use that.
Kenny Root447106f2011-03-23 11:00:15 -07002658 ps = mSettings.peekPackageLPr(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002659 }
2660 // If there was no original package, see one for the real package name.
2661 if (ps == null) {
Kenny Root447106f2011-03-23 11:00:15 -07002662 ps = mSettings.peekPackageLPr(pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002663 }
2664 // Check to see if this package could be hiding/updating a system
2665 // package. Must look for it either under the original or real
2666 // package name depending on our state.
2667 updatedPkg = mSettings.mDisabledSysPackages.get(
2668 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002669 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002670 // First check if this is a system package that may involve an update
2671 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07002672 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002673 // The path has changed from what was last scanned... check the
2674 // version of the new path against what we have stored to determine
2675 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002676 if (pkg.mVersionCode < ps.versionCode) {
2677 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002678 // Ignore entry. Skip it.
2679 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002680 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002681 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002682 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2683 return null;
2684 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002685 // The current app on the system partion is better than
2686 // what we have updated to on the data partition; switch
2687 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002688 // At this point, its safely assumed that package installation for
2689 // apps in system partition will go through. If not there won't be a working
2690 // version of the app
Kenny Root447106f2011-03-23 11:00:15 -07002691 // writer
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002692 synchronized (mPackages) {
2693 // Just remove the loaded entries from package lists.
2694 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002695 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002696 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002697 + "reverting from " + ps.codePathString
2698 + ": new version " + pkg.mVersionCode
2699 + " better than installed " + ps.versionCode);
Kenny Root85387d72010-08-26 10:13:11 -07002700 InstallArgs args = new FileInstallArgs(ps.codePathString,
2701 ps.resourcePathString, ps.nativeLibraryPathString);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002702 args.cleanUpResourcesLI();
Kenny Root447106f2011-03-23 11:00:15 -07002703 mSettings.enableSystemPackageLPw(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 }
2706 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002707 if (updatedPkg != null) {
2708 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2709 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2710 }
2711 // Verify certificates against what was last scanned
2712 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002713 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002714 return null;
2715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002716 // The apk is forward locked (not public) if its code and resources
2717 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002718 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002720 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002721 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002722
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002723 String codePath = null;
2724 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002725 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2726 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002727 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002728 } else {
2729 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002730 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002731 }
2732 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002733 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002734 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002735 codePath = pkg.mScanPath;
2736 // Set application objects path explicitly.
2737 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 // Note that we invoke the following method only if we are about to unpack an application
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002739 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 }
2741
Kenny Root85387d72010-08-26 10:13:11 -07002742 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
2743 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002744 pkg.mPath = pkg.mScanPath = destCodePath;
2745 pkg.applicationInfo.sourceDir = destCodePath;
2746 pkg.applicationInfo.publicSourceDir = destResPath;
2747 }
2748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 private static String fixProcessName(String defProcessName,
2750 String processName, int uid) {
2751 if (processName == null) {
2752 return defProcessName;
2753 }
2754 return processName;
2755 }
2756
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002757 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002758 PackageParser.Package pkg) {
2759 if (pkgSetting.signatures.mSignatures != null) {
2760 // Already existing package. Make sure signatures match
Kenny Root447106f2011-03-23 11:00:15 -07002761 if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002762 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002763 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002764 + " signatures do not match the previously installed version; ignoring!");
2765 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 return false;
2767 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002768 }
2769 // Check for shared user signatures
2770 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002771 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002772 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
2773 Slog.e(TAG, "Package " + pkg.packageName
2774 + " has no signatures that match those in shared user "
2775 + pkgSetting.sharedUser.name + "; ignoring!");
2776 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2777 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 }
2780 return true;
2781 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002782
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002783 public boolean performDexOpt(String packageName) {
2784 if (!mNoDexOpt) {
2785 return false;
2786 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002787
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002788 PackageParser.Package p;
2789 synchronized (mPackages) {
2790 p = mPackages.get(packageName);
2791 if (p == null || p.mDidDexOpt) {
2792 return false;
2793 }
2794 }
2795 synchronized (mInstallLock) {
2796 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2797 }
2798 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002799
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002800 static final int DEX_OPT_SKIPPED = 0;
2801 static final int DEX_OPT_PERFORMED = 1;
2802 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002803
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002804 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2805 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002806 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002807 String path = pkg.mScanPath;
2808 int ret = 0;
2809 try {
2810 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002811 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002812 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002813 pkg.mDidDexOpt = true;
2814 performed = true;
2815 }
2816 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002817 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002818 ret = -1;
2819 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07002820 Slog.w(TAG, "IOException reading apk: " + path, e);
2821 ret = -1;
2822 } catch (dalvik.system.StaleDexCacheError e) {
2823 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
2824 ret = -1;
2825 } catch (Exception e) {
2826 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002827 ret = -1;
2828 }
2829 if (ret < 0) {
2830 //error from installer
2831 return DEX_OPT_FAILED;
2832 }
2833 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002834
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002835 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2836 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002837
Kenny Root447106f2011-03-23 11:00:15 -07002838 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002839 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002840 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002841 + " to " + newPkg.packageName
2842 + ": old package not in system partition");
2843 return false;
2844 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002845 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002846 + " to " + newPkg.packageName
2847 + ": old package still exists");
2848 return false;
2849 }
2850 return true;
2851 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002852
Amith Yamasani0b285492011-04-14 17:35:23 -07002853 File getDataPathForUser(int userId) {
2854 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002855 }
Amith Yamasani0b285492011-04-14 17:35:23 -07002856
2857 private File getDataPathForPackage(String packageName, int userId) {
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07002858 return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
2859 + File.separator + packageName);
Amith Yamasani0b285492011-04-14 17:35:23 -07002860 }
2861
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002862 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002863 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002864 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002865 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2866 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002867 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002868 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002869 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2870 return null;
2871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 mScanningPath = scanFile;
2873 if (pkg == null) {
2874 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2875 return null;
2876 }
2877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2879 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2880 }
2881
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002882 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002883 synchronized (mPackages) {
2884 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002885 Slog.w(TAG, "*************************************************");
2886 Slog.w(TAG, "Core android package being redefined. Skipping.");
2887 Slog.w(TAG, " file=" + mScanningPath);
2888 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2890 return null;
2891 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002893 // Set up information for our fall-back user intent resolution
2894 // activity.
2895 mPlatformPackage = pkg;
2896 pkg.mVersionCode = mSdkVersion;
2897 mAndroidApplication = pkg.applicationInfo;
2898 mResolveActivity.applicationInfo = mAndroidApplication;
2899 mResolveActivity.name = ResolverActivity.class.getName();
2900 mResolveActivity.packageName = mAndroidApplication.packageName;
2901 mResolveActivity.processName = mAndroidApplication.processName;
2902 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2903 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08002904 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 mResolveActivity.exported = true;
2906 mResolveActivity.enabled = true;
2907 mResolveInfo.activityInfo = mResolveActivity;
2908 mResolveInfo.priority = 0;
2909 mResolveInfo.preferredOrder = 0;
2910 mResolveInfo.match = 0;
2911 mResolveComponentName = new ComponentName(
2912 mAndroidApplication.packageName, mResolveActivity.name);
2913 }
2914 }
2915
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002916 if (DEBUG_PACKAGE_SCANNING) {
2917 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
2918 Log.d(TAG, "Scanning package " + pkg.packageName);
2919 }
2920
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002921 if (mPackages.containsKey(pkg.packageName)
2922 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002923 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2926 return null;
2927 }
2928
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002929 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002930 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2931 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 SharedUserSetting suid = null;
2934 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002935
Kenny Root502e9a42011-01-10 13:48:15 -08002936 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002937 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002938 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002939 pkg.mRealPackage = null;
2940 pkg.mAdoptPermissions = null;
2941 }
Kenny Root502e9a42011-01-10 13:48:15 -08002942
Kenny Root447106f2011-03-23 11:00:15 -07002943 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 synchronized (mPackages) {
2945 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002946 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2947 if (mTmpSharedLibraries == null ||
2948 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2949 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2950 }
2951 int num = 0;
2952 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2953 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002954 final String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002956 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002958 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2960 return null;
2961 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002962 mTmpSharedLibraries[num] = file;
2963 num++;
2964 }
2965 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2966 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07002967 final String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
Dianne Hackborn49237342009-08-27 20:08:01 -07002968 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002969 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07002970 + " desires unavailable shared library "
2971 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2972 } else {
2973 mTmpSharedLibraries[num] = file;
2974 num++;
2975 }
2976 }
2977 if (num > 0) {
2978 pkg.usesLibraryFiles = new String[num];
2979 System.arraycopy(mTmpSharedLibraries, 0,
2980 pkg.usesLibraryFiles, 0, num);
2981 }
Kenny Root1683afa2011-01-07 14:27:50 -08002982 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 if (pkg.mSharedUserId != null) {
Kenny Root447106f2011-03-23 11:00:15 -07002985 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 pkg.applicationInfo.flags, true);
2987 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002988 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 + " for shared user failed");
2990 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2991 return null;
2992 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08002993 if (DEBUG_PACKAGE_SCANNING) {
2994 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
2995 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
2996 + "): packages=" + suid.packages);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 }
2998 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002999
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003000 // Check if we are renaming from an original package name.
3001 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003002 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08003003 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003004 // This package may need to be renamed to a previously
3005 // installed name. Let's check on that...
Kenny Root447106f2011-03-23 11:00:15 -07003006 final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08003007 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003008 // This package had originally been installed as the
3009 // original name, and we have already taken care of
3010 // transitioning to the new one. Just update the new
3011 // one to continue using the old name.
3012 realName = pkg.mRealPackage;
3013 if (!pkg.packageName.equals(renamed)) {
3014 // Callers into this function may have already taken
3015 // care of renaming the package; only do it here if
3016 // it is not already done.
3017 pkg.setPackageName(renamed);
3018 }
3019
Dianne Hackbornc1552392010-03-03 16:19:01 -08003020 } else {
3021 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
Kenny Root447106f2011-03-23 11:00:15 -07003022 if ((origPackage = mSettings.peekPackageLPr(
Dianne Hackbornc1552392010-03-03 16:19:01 -08003023 pkg.mOriginalPackages.get(i))) != null) {
3024 // We do have the package already installed under its
3025 // original name... should we use it?
Kenny Root447106f2011-03-23 11:00:15 -07003026 if (!verifyPackageUpdateLPr(origPackage, pkg)) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08003027 // New package is not compatible with original.
3028 origPackage = null;
3029 continue;
3030 } else if (origPackage.sharedUser != null) {
3031 // Make sure uid is compatible between packages.
3032 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003033 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003034 + " to " + pkg.packageName + ": old uid "
3035 + origPackage.sharedUser.name
3036 + " differs from " + pkg.mSharedUserId);
3037 origPackage = null;
3038 continue;
3039 }
3040 } else {
3041 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3042 + pkg.packageName + " to old name " + origPackage.name);
3043 }
3044 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003045 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003046 }
3047 }
3048 }
3049
3050 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003051 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003052 + " was transferred to another, but its .apk remains");
3053 }
3054
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003055 // Just create the setting, don't add it yet. For already existing packages
3056 // the PkgSetting exists already and doesn't have to be created.
Kenny Root447106f2011-03-23 11:00:15 -07003057 pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003058 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3059 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003061 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3063 return null;
3064 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003065
3066 if (pkgSetting.origPackage != null) {
3067 // If we are first transitioning from an original package,
3068 // fix up the new package's name now. We need to do this after
3069 // looking up the package under its new name, so getPackageLP
3070 // can take care of fiddling things correctly.
3071 pkg.setPackageName(origPackage.name);
3072
3073 // File a report about this.
3074 String msg = "New package " + pkgSetting.realName
3075 + " renamed to replace old package " + pkgSetting.name;
3076 reportSettingsProblem(Log.WARN, msg);
3077
3078 // Make a note of it.
3079 mTransferedPackages.add(origPackage.name);
3080
3081 // No longer need to retain this.
3082 pkgSetting.origPackage = null;
3083 }
3084
3085 if (realName != null) {
3086 // Make a note of it.
3087 mTransferedPackages.add(pkg.packageName);
3088 }
3089
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003090 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3092 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 pkg.applicationInfo.uid = pkgSetting.userId;
3095 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003096
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003097 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003098 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 return null;
3100 }
3101 // The signature has changed, but this package is in the system
3102 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003103 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003104 // However... if this package is part of a shared user, but it
3105 // doesn't match the signature of the shared user, let's fail.
3106 // What this means is that you can't change the signatures
3107 // associated with an overall shared user, which doesn't seem all
3108 // that unreasonable.
3109 if (pkgSetting.sharedUser != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003110 if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003111 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3112 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3114 return null;
3115 }
3116 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003117 // File a report about this.
3118 String msg = "System package " + pkg.packageName
3119 + " signature changed; retaining data.";
3120 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003122
The Android Open Source Project10592532009-03-18 17:39:46 -07003123 // Verify that this new package doesn't have any content providers
3124 // that conflict with existing packages. Only do this if the
3125 // package isn't already installed, since we don't want to break
3126 // things that are installed.
3127 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
Kenny Root62cc6902011-02-23 16:49:21 -08003128 final int N = pkg.providers.size();
The Android Open Source Project10592532009-03-18 17:39:46 -07003129 int i;
3130 for (i=0; i<N; i++) {
3131 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003132 if (p.info.authority != null) {
3133 String names[] = p.info.authority.split(";");
3134 for (int j = 0; j < names.length; j++) {
3135 if (mProviders.containsKey(names[j])) {
3136 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003137 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003138 " (in package " + pkg.applicationInfo.packageName +
3139 ") is already used by "
3140 + ((other != null && other.getComponentName() != null)
3141 ? other.getComponentName().getPackageName() : "?"));
3142 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3143 return null;
3144 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003145 }
3146 }
3147 }
3148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149
Kenny Root447106f2011-03-23 11:00:15 -07003150 if (pkg.mAdoptPermissions != null) {
3151 // This package wants to adopt ownership of permissions from
3152 // another package.
3153 for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
3154 final String origName = pkg.mAdoptPermissions.get(i);
3155 final PackageSetting orig = mSettings.peekPackageLPr(origName);
3156 if (orig != null) {
3157 if (verifyPackageUpdateLPr(orig, pkg)) {
3158 Slog.i(TAG, "Adopting permissions from " + origName + " to "
3159 + pkg.packageName);
3160 mSettings.transferPermissionsLPw(origName, pkg.packageName);
3161 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003162 }
3163 }
3164 }
3165 }
Kenny Root447106f2011-03-23 11:00:15 -07003166
3167 final String pkgName = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003168
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003169 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003171 pkg.applicationInfo.processName = fixProcessName(
3172 pkg.applicationInfo.packageName,
3173 pkg.applicationInfo.processName,
3174 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175
3176 File dataPath;
3177 if (mPlatformPackage == pkg) {
3178 // The system package is special.
3179 dataPath = new File (Environment.getDataDirectory(), "system");
3180 pkg.applicationInfo.dataDir = dataPath.getPath();
3181 } else {
3182 // This is a normal package, need to make its data directory.
Amith Yamasani0b285492011-04-14 17:35:23 -07003183 dataPath = getDataPathForPackage(pkg.packageName, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003184
3185 boolean uidError = false;
3186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 if (dataPath.exists()) {
3188 mOutPermissions[1] = 0;
3189 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003190
3191 // If we have mismatched owners for the data path, we have a
3192 // problem (unless we're running in the simulator.)
3193 if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 boolean recovered = false;
3195 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3196 // If this is a system app, we can at least delete its
3197 // current data so the application will still work.
3198 if (mInstaller != null) {
Amith Yamasani0b285492011-04-14 17:35:23 -07003199 int ret = mInstaller.remove(pkgName, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003200 if (ret >= 0) {
Amith Yamasani0b285492011-04-14 17:35:23 -07003201 // TODO: Kill the processes first
3202 // Remove the data directories for all users
3203 mUserManager.removePackageForAllUsers(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003204 // Old data gone!
3205 String msg = "System package " + pkg.packageName
3206 + " has changed from uid: "
3207 + mOutPermissions[1] + " to "
3208 + pkg.applicationInfo.uid + "; old data erased";
3209 reportSettingsProblem(Log.WARN, msg);
3210 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 // And now re-install the app.
Kenny Root35ab3ad2011-02-02 16:42:14 -08003213 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 pkg.applicationInfo.uid);
3215 if (ret == -1) {
3216 // Ack should not happen!
3217 msg = "System package " + pkg.packageName
3218 + " could not have data directory re-created after delete.";
3219 reportSettingsProblem(Log.WARN, msg);
3220 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3221 return null;
3222 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003223 // Create data directories for all users
3224 mUserManager.installPackageForAllUsers(pkgName,
3225 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 if (!recovered) {
3229 mHasSystemUidErrors = true;
3230 }
3231 }
3232 if (!recovered) {
3233 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3234 + pkg.applicationInfo.uid + "/fs_"
3235 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003236 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 String msg = "Package " + pkg.packageName
3238 + " has mismatched uid: "
3239 + mOutPermissions[1] + " on disk, "
3240 + pkg.applicationInfo.uid + " in settings";
Kenny Root447106f2011-03-23 11:00:15 -07003241 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003242 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003243 mSettings.mReadMessages.append(msg);
3244 mSettings.mReadMessages.append('\n');
3245 uidError = true;
3246 if (!pkgSetting.uidError) {
3247 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
3250 }
3251 }
3252 pkg.applicationInfo.dataDir = dataPath.getPath();
3253 } else {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003254 if (DEBUG_PACKAGE_SCANNING) {
3255 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3256 Log.v(TAG, "Want this data dir: " + dataPath);
3257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 //invoke installer to do the actual installation
3259 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08003260 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 pkg.applicationInfo.uid);
Amith Yamasani0b285492011-04-14 17:35:23 -07003262 if (ret < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003263 // Error from installer
3264 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3265 return null;
3266 }
Amith Yamasani0b285492011-04-14 17:35:23 -07003267 // Create data directories for all users
3268 mUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 } else {
3270 dataPath.mkdirs();
3271 if (dataPath.exists()) {
3272 FileUtils.setPermissions(
3273 dataPath.toString(),
3274 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3275 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
3276 }
3277 }
3278 if (dataPath.exists()) {
3279 pkg.applicationInfo.dataDir = dataPath.getPath();
3280 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003281 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 pkg.applicationInfo.dataDir = null;
3283 }
3284 }
Kenny Root85387d72010-08-26 10:13:11 -07003285
3286 /*
3287 * Set the data dir to the default "/data/data/<package name>/lib"
3288 * if we got here without anyone telling us different (e.g., apps
3289 * stored on SD card have their native libraries stored in the ASEC
3290 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003291 *
3292 * This happens during an upgrade from a package settings file that
3293 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003294 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003295 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3296 if (pkgSetting.nativeLibraryPathString == null) {
3297 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3298 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3299 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3300 } else {
3301 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3302 }
Kenny Root85387d72010-08-26 10:13:11 -07003303 }
3304
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003305 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 }
3307
Kenny Root85387d72010-08-26 10:13:11 -07003308 // If we're running in the simulator, we don't need to unpack anything.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 if (mInstaller != null) {
3310 String path = scanFile.getPath();
Kenny Root85387d72010-08-26 10:13:11 -07003311 /* Note: We don't want to unpack the native binaries for
3312 * system applications, unless they have been updated
3313 * (the binaries are already under /system/lib).
3314 * Also, don't unpack libs for apps on the external card
3315 * since they should have their libraries in the ASEC
3316 * container already.
3317 *
3318 * In other words, we're going to unpack the binaries
3319 * only for non-system apps and system app upgrades.
3320 */
Kenny Root831baa22010-10-05 12:29:25 -07003321 if (pkg.applicationInfo.nativeLibraryDir != null) {
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003322 try {
3323 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
3324 final String dataPathString = dataPath.getCanonicalFile().getPath();
Kenny Roote68d58a2010-10-18 16:08:54 -07003325
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003326 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3327 /*
3328 * Upgrading from a previous version of the OS sometimes
3329 * leaves native libraries in the /data/data/<app>/lib
3330 * directory for system apps even when they shouldn't be.
3331 * Recent changes in the JNI library search path
3332 * necessitates we remove those to match previous behavior.
3333 */
3334 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
3335 Log.i(TAG, "removed obsolete native libraries for system package "
3336 + path);
3337 }
3338 } else if (nativeLibraryDir.getCanonicalFile().getParent()
3339 .equals(dataPathString)) {
3340 /*
3341 * If this is an internal application or our
3342 * nativeLibraryPath points to our data directory, unpack
3343 * the libraries. The native library path pointing to the
3344 * data directory for an application in an ASEC container
3345 * can happen for older apps that existed before an OTA to
3346 * Gingerbread.
3347 */
3348 Slog.i(TAG, "Unpacking native libraries for " + path);
3349 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3350 NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
3351 } else {
3352 Slog.i(TAG, "Linking native library dir for " + path);
3353 mInstaller.linkNativeLibraryDirectory(dataPathString,
3354 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003355 }
Amith Yamasani0f3f29b2011-05-09 14:17:14 -07003356 } catch (IOException ioe) {
3357 Log.e(TAG, "Unable to get canonical file " + ioe.toString());
Kenny Root831baa22010-10-05 12:29:25 -07003358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003360 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003361
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003362 if ((scanMode&SCAN_NO_DEX) == 0) {
3363 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3365 return null;
3366 }
3367 }
3368 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 if (mFactoryTest && pkg.requestedPermissions.contains(
3371 android.Manifest.permission.FACTORY_TEST)) {
3372 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3373 }
3374
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003375 // Request the ActivityManager to kill the process(only for existing packages)
3376 // so that we do not end up in a confused state while the user is still using the older
3377 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003378 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003379 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003380 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003381 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003382
Kenny Root447106f2011-03-23 11:00:15 -07003383 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003385 // We don't expect installation to fail beyond this point,
3386 if ((scanMode&SCAN_MONITOR) != 0) {
3387 mAppDirs.put(pkg.mPath, pkg);
3388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 // Add the new setting to mSettings
Kenny Root447106f2011-03-23 11:00:15 -07003390 mSettings.insertPackageSettingLPw(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003392 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003393 // Make sure we don't accidentally delete its data.
3394 mSettings.mPackagesToBeCleaned.remove(pkgName);
3395
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003396 // Take care of first install / last update times.
3397 if (currentTime != 0) {
3398 if (pkgSetting.firstInstallTime == 0) {
3399 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
3400 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
3401 pkgSetting.lastUpdateTime = currentTime;
3402 }
3403 } else if (pkgSetting.firstInstallTime == 0) {
3404 // We need *something*. Take time time stamp of the file.
3405 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
3406 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
3407 if (scanFileTime != pkgSetting.timeStamp) {
3408 // A package on the system image has changed; consider this
3409 // to be an update.
3410 pkgSetting.lastUpdateTime = scanFileTime;
3411 }
3412 }
3413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003414 int N = pkg.providers.size();
3415 StringBuilder r = null;
3416 int i;
3417 for (i=0; i<N; i++) {
3418 PackageParser.Provider p = pkg.providers.get(i);
3419 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3420 p.info.processName, pkg.applicationInfo.uid);
3421 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3422 p.info.name), p);
3423 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003424 if (p.info.authority != null) {
3425 String names[] = p.info.authority.split(";");
3426 p.info.authority = null;
3427 for (int j = 0; j < names.length; j++) {
3428 if (j == 1 && p.syncable) {
3429 // We only want the first authority for a provider to possibly be
3430 // syncable, so if we already added this provider using a different
3431 // authority clear the syncable flag. We copy the provider before
3432 // changing it because the mProviders object contains a reference
3433 // to a provider that we don't want to change.
3434 // Only do this for the second authority since the resulting provider
3435 // object can be the same for all future authorities for this provider.
3436 p = new PackageParser.Provider(p);
3437 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003439 if (!mProviders.containsKey(names[j])) {
3440 mProviders.put(names[j], p);
3441 if (p.info.authority == null) {
3442 p.info.authority = names[j];
3443 } else {
3444 p.info.authority = p.info.authority + ";" + names[j];
3445 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003446 if (DEBUG_PACKAGE_SCANNING) {
3447 if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
3448 Log.d(TAG, "Registered content provider: " + names[j]
3449 + ", className = " + p.info.name + ", isSyncable = "
3450 + p.info.isSyncable);
3451 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003452 } else {
3453 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003454 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003455 " (in package " + pkg.applicationInfo.packageName +
3456 "): name already used by "
3457 + ((other != null && other.getComponentName() != null)
3458 ? other.getComponentName().getPackageName() : "?"));
3459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 }
3461 }
3462 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3463 if (r == null) {
3464 r = new StringBuilder(256);
3465 } else {
3466 r.append(' ');
3467 }
3468 r.append(p.info.name);
3469 }
3470 }
3471 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003472 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 N = pkg.services.size();
3476 r = null;
3477 for (i=0; i<N; i++) {
3478 PackageParser.Service s = pkg.services.get(i);
3479 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3480 s.info.processName, pkg.applicationInfo.uid);
3481 mServices.addService(s);
3482 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3483 if (r == null) {
3484 r = new StringBuilder(256);
3485 } else {
3486 r.append(' ');
3487 }
3488 r.append(s.info.name);
3489 }
3490 }
3491 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003492 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 N = pkg.receivers.size();
3496 r = null;
3497 for (i=0; i<N; i++) {
3498 PackageParser.Activity a = pkg.receivers.get(i);
3499 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3500 a.info.processName, pkg.applicationInfo.uid);
3501 mReceivers.addActivity(a, "receiver");
3502 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3503 if (r == null) {
3504 r = new StringBuilder(256);
3505 } else {
3506 r.append(' ');
3507 }
3508 r.append(a.info.name);
3509 }
3510 }
3511 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003512 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 N = pkg.activities.size();
3516 r = null;
3517 for (i=0; i<N; i++) {
3518 PackageParser.Activity a = pkg.activities.get(i);
3519 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3520 a.info.processName, pkg.applicationInfo.uid);
3521 mActivities.addActivity(a, "activity");
3522 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3523 if (r == null) {
3524 r = new StringBuilder(256);
3525 } else {
3526 r.append(' ');
3527 }
3528 r.append(a.info.name);
3529 }
3530 }
3531 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003532 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003533 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003535 N = pkg.permissionGroups.size();
3536 r = null;
3537 for (i=0; i<N; i++) {
3538 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3539 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3540 if (cur == null) {
3541 mPermissionGroups.put(pg.info.name, pg);
3542 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3543 if (r == null) {
3544 r = new StringBuilder(256);
3545 } else {
3546 r.append(' ');
3547 }
3548 r.append(pg.info.name);
3549 }
3550 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003551 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 + pg.info.packageName + " ignored: original from "
3553 + cur.info.packageName);
3554 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3555 if (r == null) {
3556 r = new StringBuilder(256);
3557 } else {
3558 r.append(' ');
3559 }
3560 r.append("DUP:");
3561 r.append(pg.info.name);
3562 }
3563 }
3564 }
3565 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003566 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 N = pkg.permissions.size();
3570 r = null;
3571 for (i=0; i<N; i++) {
3572 PackageParser.Permission p = pkg.permissions.get(i);
3573 HashMap<String, BasePermission> permissionMap =
3574 p.tree ? mSettings.mPermissionTrees
3575 : mSettings.mPermissions;
3576 p.group = mPermissionGroups.get(p.info.group);
3577 if (p.info.group == null || p.group != null) {
3578 BasePermission bp = permissionMap.get(p.info.name);
3579 if (bp == null) {
3580 bp = new BasePermission(p.info.name, p.info.packageName,
3581 BasePermission.TYPE_NORMAL);
3582 permissionMap.put(p.info.name, bp);
3583 }
3584 if (bp.perm == null) {
3585 if (bp.sourcePackage == null
3586 || bp.sourcePackage.equals(p.info.packageName)) {
3587 BasePermission tree = findPermissionTreeLP(p.info.name);
3588 if (tree == null
3589 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003590 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 bp.perm = p;
3592 bp.uid = pkg.applicationInfo.uid;
3593 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3594 if (r == null) {
3595 r = new StringBuilder(256);
3596 } else {
3597 r.append(' ');
3598 }
3599 r.append(p.info.name);
3600 }
3601 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003602 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 + p.info.packageName + " ignored: base tree "
3604 + tree.name + " is from package "
3605 + tree.sourcePackage);
3606 }
3607 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003608 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003609 + p.info.packageName + " ignored: original from "
3610 + bp.sourcePackage);
3611 }
3612 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3613 if (r == null) {
3614 r = new StringBuilder(256);
3615 } else {
3616 r.append(' ');
3617 }
3618 r.append("DUP:");
3619 r.append(p.info.name);
3620 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003621 if (bp.perm == p) {
3622 bp.protectionLevel = p.info.protectionLevel;
3623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003625 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 + p.info.packageName + " ignored: no group "
3627 + p.group);
3628 }
3629 }
3630 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003631 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 N = pkg.instrumentation.size();
3635 r = null;
3636 for (i=0; i<N; i++) {
3637 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3638 a.info.packageName = pkg.applicationInfo.packageName;
3639 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3640 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3641 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07003642 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003643 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3645 if (r == null) {
3646 r = new StringBuilder(256);
3647 } else {
3648 r.append(' ');
3649 }
3650 r.append(a.info.name);
3651 }
3652 }
3653 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003654 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003655 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003656
Dianne Hackborn854060af2009-07-09 18:14:31 -07003657 if (pkg.protectedBroadcasts != null) {
3658 N = pkg.protectedBroadcasts.size();
3659 for (i=0; i<N; i++) {
3660 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3661 }
3662 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 pkgSetting.setTimeStamp(scanFileTime);
3665 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 return pkg;
3668 }
3669
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003670 private void killApplication(String pkgName, int uid) {
3671 // Request the ActivityManager to kill the process(only for existing packages)
3672 // so that we do not end up in a confused state while the user is still using the older
3673 // version of the application while the new one gets installed.
3674 IActivityManager am = ActivityManagerNative.getDefault();
3675 if (am != null) {
3676 try {
3677 am.killApplicationWithUid(pkgName, uid);
3678 } catch (RemoteException e) {
3679 }
3680 }
3681 }
3682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003684 if (DEBUG_INSTALL) {
3685 if (chatty)
3686 Log.d(TAG, "Removing package " + pkg.applicationInfo.packageName);
3687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688
Kenny Root447106f2011-03-23 11:00:15 -07003689 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003690 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07003691 clearPackagePreferredActivitiesLPw(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 mPackages.remove(pkg.applicationInfo.packageName);
3694 if (pkg.mPath != null) {
3695 mAppDirs.remove(pkg.mPath);
3696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 int N = pkg.providers.size();
3699 StringBuilder r = null;
3700 int i;
3701 for (i=0; i<N; i++) {
3702 PackageParser.Provider p = pkg.providers.get(i);
3703 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3704 p.info.name));
3705 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 /* The is another ContentProvider with this authority when
3708 * this app was installed so this authority is null,
3709 * Ignore it as we don't have to unregister the provider.
3710 */
3711 continue;
3712 }
3713 String names[] = p.info.authority.split(";");
3714 for (int j = 0; j < names.length; j++) {
3715 if (mProviders.get(names[j]) == p) {
3716 mProviders.remove(names[j]);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003717 if (DEBUG_REMOVE) {
3718 if (chatty)
3719 Log.d(TAG, "Unregistered content provider: " + names[j]
3720 + ", className = " + p.info.name + ", isSyncable = "
3721 + p.info.isSyncable);
3722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 }
3724 }
3725 if (chatty) {
3726 if (r == null) {
3727 r = new StringBuilder(256);
3728 } else {
3729 r.append(' ');
3730 }
3731 r.append(p.info.name);
3732 }
3733 }
3734 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003735 if (DEBUG_REMOVE) Log.d(TAG, " Providers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003738 N = pkg.services.size();
3739 r = null;
3740 for (i=0; i<N; i++) {
3741 PackageParser.Service s = pkg.services.get(i);
3742 mServices.removeService(s);
3743 if (chatty) {
3744 if (r == null) {
3745 r = new StringBuilder(256);
3746 } else {
3747 r.append(' ');
3748 }
3749 r.append(s.info.name);
3750 }
3751 }
3752 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003753 if (DEBUG_REMOVE) Log.d(TAG, " Services: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 N = pkg.receivers.size();
3757 r = null;
3758 for (i=0; i<N; i++) {
3759 PackageParser.Activity a = pkg.receivers.get(i);
3760 mReceivers.removeActivity(a, "receiver");
3761 if (chatty) {
3762 if (r == null) {
3763 r = new StringBuilder(256);
3764 } else {
3765 r.append(' ');
3766 }
3767 r.append(a.info.name);
3768 }
3769 }
3770 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003771 if (DEBUG_REMOVE) Log.d(TAG, " Receivers: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 N = pkg.activities.size();
3775 r = null;
3776 for (i=0; i<N; i++) {
3777 PackageParser.Activity a = pkg.activities.get(i);
3778 mActivities.removeActivity(a, "activity");
3779 if (chatty) {
3780 if (r == null) {
3781 r = new StringBuilder(256);
3782 } else {
3783 r.append(' ');
3784 }
3785 r.append(a.info.name);
3786 }
3787 }
3788 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003789 if (DEBUG_REMOVE) Log.d(TAG, " Activities: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 N = pkg.permissions.size();
3793 r = null;
3794 for (i=0; i<N; i++) {
3795 PackageParser.Permission p = pkg.permissions.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3797 if (bp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 bp = mSettings.mPermissionTrees.get(p.info.name);
3799 }
3800 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003801 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 if (chatty) {
3803 if (r == null) {
3804 r = new StringBuilder(256);
3805 } else {
3806 r.append(' ');
3807 }
3808 r.append(p.info.name);
3809 }
3810 }
3811 }
3812 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003813 if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 N = pkg.instrumentation.size();
3817 r = null;
3818 for (i=0; i<N; i++) {
3819 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003820 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 if (chatty) {
3822 if (r == null) {
3823 r = new StringBuilder(256);
3824 } else {
3825 r.append(' ');
3826 }
3827 r.append(a.info.name);
3828 }
3829 }
3830 if (r != null) {
Kenny Root9718cf52011-02-23 16:45:26 -08003831 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 }
3833 }
3834 }
3835
3836 private static final boolean isPackageFilename(String name) {
3837 return name != null && name.endsWith(".apk");
3838 }
3839
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003840 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
3841 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
3842 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
3843 return true;
3844 }
3845 }
3846 return false;
3847 }
3848
Kenny Root447106f2011-03-23 11:00:15 -07003849 private void updatePermissionsLPw(String changingPkg,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07003850 PackageParser.Package pkgInfo, boolean grantPermissions,
3851 boolean replace, boolean replaceAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003852 // Make sure there are no dangling permission trees.
Kenny Root447106f2011-03-23 11:00:15 -07003853 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003855 final BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003856 if (bp.packageSetting == null) {
3857 // We may not yet have parsed the package, so just see if
3858 // we still know about its settings.
3859 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3860 }
3861 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003862 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 + " from package " + bp.sourcePackage);
3864 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003865 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3866 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3867 Slog.i(TAG, "Removing old permission tree: " + bp.name
3868 + " from package " + bp.sourcePackage);
3869 grantPermissions = true;
3870 it.remove();
3871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 }
3873 }
3874
3875 // Make sure all dynamic permissions have been assigned to a package,
3876 // and make sure there are no dangling permissions.
3877 it = mSettings.mPermissions.values().iterator();
3878 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07003879 final BasePermission bp = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003880 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3881 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3882 + bp.name + " pkg=" + bp.sourcePackage
3883 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003884 if (bp.packageSetting == null && bp.pendingInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003885 final BasePermission tree = findPermissionTreeLP(bp.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 if (tree != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003887 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003888 bp.perm = new PackageParser.Permission(tree.perm.owner,
3889 new PermissionInfo(bp.pendingInfo));
3890 bp.perm.info.packageName = tree.perm.info.packageName;
3891 bp.perm.info.name = bp.name;
3892 bp.uid = tree.uid;
3893 }
3894 }
3895 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003896 if (bp.packageSetting == null) {
3897 // We may not yet have parsed the package, so just see if
3898 // we still know about its settings.
3899 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3900 }
3901 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003902 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003903 + " from package " + bp.sourcePackage);
3904 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003905 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3906 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3907 Slog.i(TAG, "Removing old permission: " + bp.name
3908 + " from package " + bp.sourcePackage);
3909 grantPermissions = true;
3910 it.remove();
3911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 }
3913 }
3914
3915 // Now update the permissions for all packages, in particular
3916 // replace the granted permissions of the system packages.
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003917 if (grantPermissions) {
3918 for (PackageParser.Package pkg : mPackages.values()) {
3919 if (pkg != pkgInfo) {
Kenny Root447106f2011-03-23 11:00:15 -07003920 grantPermissionsLPw(pkg, replaceAll);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003921 }
3922 }
3923 }
3924
3925 if (pkgInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07003926 grantPermissionsLPw(pkgInfo, replace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 }
3928 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003929
Kenny Root447106f2011-03-23 11:00:15 -07003930 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace) {
3931 final PackageSetting ps = (PackageSetting) pkg.mExtras;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 if (ps == null) {
3933 return;
3934 }
3935 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003936 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 if (replace) {
3939 ps.permissionsFixed = false;
3940 if (gp == ps) {
3941 gp.grantedPermissions.clear();
3942 gp.gids = mGlobalGids;
3943 }
3944 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003946 if (gp.gids == null) {
3947 gp.gids = mGlobalGids;
3948 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 final int N = pkg.requestedPermissions.size();
3951 for (int i=0; i<N; i++) {
Kenny Root447106f2011-03-23 11:00:15 -07003952 final String name = pkg.requestedPermissions.get(i);
3953 final BasePermission bp = mSettings.mPermissions.get(name);
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003954 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 if (gp != ps) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08003956 Log.i(TAG, "Package " + pkg.packageName + " checking " + name + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 }
3958 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003959 if (bp != null && bp.packageSetting != null) {
3960 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003962 boolean allowedSig = false;
3963 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3964 || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003965 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07003966 } else if (bp.packageSetting == null) {
3967 // This permission is invalid; skip it.
3968 allowed = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003969 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3970 || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Kenny Root447106f2011-03-23 11:00:15 -07003971 allowed = (compareSignatures(
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003972 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 == PackageManager.SIGNATURE_MATCH)
Kenny Root447106f2011-03-23 11:00:15 -07003974 || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003976 if (!allowed && bp.protectionLevel
3977 == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Kenny Root85387d72010-08-26 10:13:11 -07003978 if (isSystemApp(pkg)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 // For updated system applications, the signatureOrSystem permission
3980 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07003981 if (isUpdatedSystemApp(pkg)) {
Kenny Root447106f2011-03-23 11:00:15 -07003982 final PackageSetting sysPs = mSettings
3983 .getDisabledSystemPkgLPr(pkg.packageName);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003984 final GrantedPermissions origGp = sysPs.sharedUser != null
3985 ? sysPs.sharedUser : sysPs;
3986 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 allowed = true;
3988 } else {
3989 allowed = false;
3990 }
3991 } else {
3992 allowed = true;
3993 }
3994 }
3995 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003996 if (allowed) {
3997 allowedSig = true;
3998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 } else {
4000 allowed = false;
4001 }
Kenny Root4dfe6ff2011-02-23 17:00:43 -08004002 if (DEBUG_INSTALL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 if (gp != ps) {
4004 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4005 }
4006 }
4007 if (allowed) {
4008 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4009 && ps.permissionsFixed) {
4010 // If this is an existing, non-system package, then
4011 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004012 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004014 // Except... if this is a permission that was added
4015 // to the platform (note: need to only do this when
4016 // updating the platform).
4017 final int NP = PackageParser.NEW_PERMISSIONS.length;
4018 for (int ip=0; ip<NP; ip++) {
4019 final PackageParser.NewPermissionInfo npi
4020 = PackageParser.NEW_PERMISSIONS[ip];
4021 if (npi.name.equals(perm)
4022 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4023 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004024 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004025 + pkg.packageName);
4026 break;
4027 }
4028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 }
4030 }
4031 if (allowed) {
4032 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004033 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 gp.grantedPermissions.add(perm);
4035 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004036 } else if (!ps.haveGids) {
4037 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 }
4039 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004040 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 + " to package " + pkg.packageName
4042 + " because it was previously installed without");
4043 }
4044 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004045 if (gp.grantedPermissions.remove(perm)) {
4046 changedPermission = true;
4047 gp.gids = removeInts(gp.gids, bp.gids);
4048 Slog.i(TAG, "Un-granting permission " + perm
4049 + " from package " + pkg.packageName
4050 + " (protectionLevel=" + bp.protectionLevel
4051 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4052 + ")");
4053 } else {
4054 Slog.w(TAG, "Not granting permission " + perm
4055 + " to package " + pkg.packageName
4056 + " (protectionLevel=" + bp.protectionLevel
4057 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4058 + ")");
4059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 }
4061 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004062 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 + " in package " + pkg.packageName);
4064 }
4065 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004066
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004067 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004068 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4069 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 // This is the first that we have heard about this package, so the
4071 // permissions we have now selected are fixed until explicitly
4072 // changed.
4073 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004075 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 private final class ActivityIntentResolver
4079 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004080 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
4081 boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004083 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004084 }
4085
Kenny Root60f7ad82011-03-22 12:49:06 -07004086 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004087 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004088 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4090 }
4091
Kenny Root60f7ad82011-03-22 12:49:06 -07004092 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
4093 int flags, ArrayList<PackageParser.Activity> packageActivities) {
Mihai Predaeae850c2009-05-13 10:13:48 +02004094 if (packageActivities == null) {
4095 return null;
4096 }
4097 mFlags = flags;
4098 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004099 final int N = packageActivities.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004100 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4101 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004102
4103 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004104 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004105 intentFilters = packageActivities.get(i).intents;
4106 if (intentFilters != null && intentFilters.size() > 0) {
4107 listCut.add(intentFilters);
4108 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004109 }
4110 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4111 }
4112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004114 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004115 mActivities.put(a.getComponentName(), a);
Kenny Root9718cf52011-02-23 16:45:26 -08004116 if (DEBUG_SHOW_INFO)
4117 Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 TAG, " " + type + " " +
4119 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004120 if (DEBUG_SHOW_INFO)
4121 Log.v(TAG, " Class=" + a.info.name);
Kenny Root62cc6902011-02-23 16:49:21 -08004122 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004123 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004125 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4126 intent.setPriority(0);
4127 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4128 + a.className + " with priority > 0, forcing to 0");
4129 }
Kenny Root9718cf52011-02-23 16:45:26 -08004130 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 Log.v(TAG, " IntentFilter:");
4132 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4133 }
4134 if (!intent.debugCheck()) {
4135 Log.w(TAG, "==> For Activity " + a.info.name);
4136 }
4137 addFilter(intent);
4138 }
4139 }
4140
4141 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004142 mActivities.remove(a.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004143 if (DEBUG_SHOW_INFO) {
4144 Log.v(TAG, " " + type + " "
4145 + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
4146 : a.info.name) + ":");
4147 Log.v(TAG, " Class=" + a.info.name);
4148 }
4149 final int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004150 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004152 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 Log.v(TAG, " IntentFilter:");
4154 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4155 }
4156 removeFilter(intent);
4157 }
4158 }
4159
4160 @Override
4161 protected boolean allowFilterResult(
4162 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4163 ActivityInfo filterAi = filter.activity.info;
4164 for (int i=dest.size()-1; i>=0; i--) {
4165 ActivityInfo destAi = dest.get(i).activityInfo;
4166 if (destAi.name == filterAi.name
4167 && destAi.packageName == filterAi.packageName) {
4168 return false;
4169 }
4170 }
4171 return true;
4172 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 @Override
Dianne Hackborne7f97212011-02-24 14:40:20 -08004175 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter) {
4176 PackageParser.Package p = filter.activity.owner;
4177 if (p != null) {
4178 PackageSetting ps = (PackageSetting)p.mExtras;
4179 if (ps != null) {
4180 return ps.stopped;
4181 }
4182 }
4183 return false;
4184 }
4185
4186 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004187 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4188 return info.activity.owner.packageName;
4189 }
4190
4191 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004192 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
4193 int match) {
Kenny Root447106f2011-03-23 11:00:15 -07004194 if (!mSettings.isEnabledLPr(info.activity.info, mFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004195 return null;
4196 }
4197 final PackageParser.Activity activity = info.activity;
4198 if (mSafeMode && (activity.info.applicationInfo.flags
4199 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4200 return null;
4201 }
4202 final ResolveInfo res = new ResolveInfo();
4203 res.activityInfo = PackageParser.generateActivityInfo(activity,
4204 mFlags);
4205 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4206 res.filter = info;
4207 }
4208 res.priority = info.getPriority();
4209 res.preferredOrder = activity.owner.mPreferredOrder;
4210 //System.out.println("Result: " + res.activityInfo.className +
4211 // " = " + res.priority);
4212 res.match = match;
4213 res.isDefault = info.hasDefault;
4214 res.labelRes = info.labelRes;
4215 res.nonLocalizedLabel = info.nonLocalizedLabel;
4216 res.icon = info.icon;
4217 return res;
4218 }
4219
4220 @Override
4221 protected void sortResults(List<ResolveInfo> results) {
4222 Collections.sort(results, mResolvePrioritySorter);
4223 }
4224
4225 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004226 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004227 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004228 out.print(prefix); out.print(
4229 Integer.toHexString(System.identityHashCode(filter.activity)));
4230 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004231 out.print(filter.activity.getComponentShortName());
4232 out.print(" filter ");
4233 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 }
4235
4236// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4237// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4238// final List<ResolveInfo> retList = Lists.newArrayList();
4239// while (i.hasNext()) {
4240// final ResolveInfo resolveInfo = i.next();
4241// if (isEnabledLP(resolveInfo.activityInfo)) {
4242// retList.add(resolveInfo);
4243// }
4244// }
4245// return retList;
4246// }
4247
4248 // Keys are String (activity class name), values are Activity.
4249 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4250 = new HashMap<ComponentName, PackageParser.Activity>();
4251 private int mFlags;
4252 }
4253
4254 private final class ServiceIntentResolver
4255 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Kenny Root60f7ad82011-03-22 12:49:06 -07004256 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
4257 boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004259 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004260 }
4261
Kenny Root60f7ad82011-03-22 12:49:06 -07004262 public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004263 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004264 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4266 }
4267
Kenny Root60f7ad82011-03-22 12:49:06 -07004268 public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
4269 int flags, ArrayList<PackageParser.Service> packageServices) {
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004270 if (packageServices == null) {
4271 return null;
4272 }
4273 mFlags = flags;
4274 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
Kenny Root62cc6902011-02-23 16:49:21 -08004275 final int N = packageServices.size();
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07004276 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4277 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4278
4279 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4280 for (int i = 0; i < N; ++i) {
4281 intentFilters = packageServices.get(i).intents;
4282 if (intentFilters != null && intentFilters.size() > 0) {
4283 listCut.add(intentFilters);
4284 }
4285 }
4286 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4287 }
4288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004290 mServices.put(s.getComponentName(), s);
Kenny Root9718cf52011-02-23 16:45:26 -08004291 if (DEBUG_SHOW_INFO) {
4292 Log.v(TAG, " "
4293 + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004295 Log.v(TAG, " Class=" + s.info.name);
4296 }
4297 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 int j;
4299 for (j=0; j<NI; j++) {
4300 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004301 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 Log.v(TAG, " IntentFilter:");
4303 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4304 }
4305 if (!intent.debugCheck()) {
4306 Log.w(TAG, "==> For Service " + s.info.name);
4307 }
4308 addFilter(intent);
4309 }
4310 }
4311
4312 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004313 mServices.remove(s.getComponentName());
Kenny Root9718cf52011-02-23 16:45:26 -08004314 if (DEBUG_SHOW_INFO) {
4315 Log.v(TAG, " " + (s.info.nonLocalizedLabel != null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 ? s.info.nonLocalizedLabel : s.info.name) + ":");
Kenny Root9718cf52011-02-23 16:45:26 -08004317 Log.v(TAG, " Class=" + s.info.name);
4318 }
4319 final int NI = s.intents.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 int j;
4321 for (j=0; j<NI; j++) {
4322 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
Kenny Root9718cf52011-02-23 16:45:26 -08004323 if (DEBUG_SHOW_INFO) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 Log.v(TAG, " IntentFilter:");
4325 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4326 }
4327 removeFilter(intent);
4328 }
4329 }
4330
4331 @Override
4332 protected boolean allowFilterResult(
4333 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4334 ServiceInfo filterSi = filter.service.info;
4335 for (int i=dest.size()-1; i>=0; i--) {
4336 ServiceInfo destAi = dest.get(i).serviceInfo;
4337 if (destAi.name == filterSi.name
4338 && destAi.packageName == filterSi.packageName) {
4339 return false;
4340 }
4341 }
4342 return true;
4343 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 @Override
Dianne Hackborne7f97212011-02-24 14:40:20 -08004346 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter) {
4347 PackageParser.Package p = filter.service.owner;
4348 if (p != null) {
4349 PackageSetting ps = (PackageSetting)p.mExtras;
4350 if (ps != null) {
4351 return ps.stopped;
4352 }
4353 }
4354 return false;
4355 }
4356
4357 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004358 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
4359 return info.service.owner.packageName;
4360 }
4361
4362 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4364 int match) {
Jason parksa3cdaa52011-01-13 14:15:43 -06004365 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
Kenny Root447106f2011-03-23 11:00:15 -07004366 if (!mSettings.isEnabledLPr(info.service.info, mFlags)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 return null;
4368 }
4369 final PackageParser.Service service = info.service;
4370 if (mSafeMode && (service.info.applicationInfo.flags
4371 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4372 return null;
4373 }
4374 final ResolveInfo res = new ResolveInfo();
4375 res.serviceInfo = PackageParser.generateServiceInfo(service,
4376 mFlags);
4377 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4378 res.filter = filter;
4379 }
4380 res.priority = info.getPriority();
4381 res.preferredOrder = service.owner.mPreferredOrder;
4382 //System.out.println("Result: " + res.activityInfo.className +
4383 // " = " + res.priority);
4384 res.match = match;
4385 res.isDefault = info.hasDefault;
4386 res.labelRes = info.labelRes;
4387 res.nonLocalizedLabel = info.nonLocalizedLabel;
4388 res.icon = info.icon;
4389 return res;
4390 }
4391
4392 @Override
4393 protected void sortResults(List<ResolveInfo> results) {
4394 Collections.sort(results, mResolvePrioritySorter);
4395 }
4396
4397 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004398 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004400 out.print(prefix); out.print(
4401 Integer.toHexString(System.identityHashCode(filter.service)));
4402 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004403 out.print(filter.service.getComponentShortName());
4404 out.print(" filter ");
4405 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407
4408// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4409// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4410// final List<ResolveInfo> retList = Lists.newArrayList();
4411// while (i.hasNext()) {
4412// final ResolveInfo resolveInfo = (ResolveInfo) i;
4413// if (isEnabledLP(resolveInfo.serviceInfo)) {
4414// retList.add(resolveInfo);
4415// }
4416// }
4417// return retList;
4418// }
4419
4420 // Keys are String (activity class name), values are Activity.
4421 private final HashMap<ComponentName, PackageParser.Service> mServices
4422 = new HashMap<ComponentName, PackageParser.Service>();
4423 private int mFlags;
4424 };
4425
4426 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4427 new Comparator<ResolveInfo>() {
4428 public int compare(ResolveInfo r1, ResolveInfo r2) {
4429 int v1 = r1.priority;
4430 int v2 = r2.priority;
4431 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4432 if (v1 != v2) {
4433 return (v1 > v2) ? -1 : 1;
4434 }
4435 v1 = r1.preferredOrder;
4436 v2 = r2.preferredOrder;
4437 if (v1 != v2) {
4438 return (v1 > v2) ? -1 : 1;
4439 }
4440 if (r1.isDefault != r2.isDefault) {
4441 return r1.isDefault ? -1 : 1;
4442 }
4443 v1 = r1.match;
4444 v2 = r2.match;
4445 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4446 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4447 }
4448 };
4449
4450 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4451 new Comparator<ProviderInfo>() {
4452 public int compare(ProviderInfo p1, ProviderInfo p2) {
4453 final int v1 = p1.initOrder;
4454 final int v2 = p2.initOrder;
4455 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4456 }
4457 };
4458
Kenny Root447106f2011-03-23 11:00:15 -07004459 static final void sendPackageBroadcast(String action, String pkg,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004460 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 IActivityManager am = ActivityManagerNative.getDefault();
4462 if (am != null) {
4463 try {
4464 final Intent intent = new Intent(action,
4465 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4466 if (extras != null) {
4467 intent.putExtras(extras);
4468 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08004469 if (targetPkg != null) {
4470 intent.setPackage(targetPkg);
4471 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004472 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004473 am.broadcastIntent(null, intent, null, finishedReceiver,
4474 0, null, null, null, finishedReceiver != null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 } catch (RemoteException ex) {
4476 }
4477 }
4478 }
Kenny Root300c13a2011-01-18 13:04:40 -08004479
4480 /**
4481 * Check if the external storage media is available. This is true if there
4482 * is a mounted external storage medium or if the external storage is
4483 * emulated.
4484 */
4485 private boolean isExternalMediaAvailable() {
4486 return mMediaMounted || Environment.isExternalStorageEmulated();
4487 }
4488
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004489 public String nextPackageToClean(String lastPackage) {
Kenny Root447106f2011-03-23 11:00:15 -07004490 // writer
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004491 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08004492 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004493 // If the external storage is no longer mounted at this point,
4494 // the caller may not have been able to delete all of this
4495 // packages files and can not delete any more. Bail.
4496 return null;
4497 }
4498 if (lastPackage != null) {
4499 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4500 }
4501 return mSettings.mPackagesToBeCleaned.size() > 0
4502 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4503 }
4504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004506 void schedulePackageCleaning(String packageName) {
4507 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4508 }
4509
4510 void startCleaningPackages() {
Kenny Root447106f2011-03-23 11:00:15 -07004511 // reader
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004512 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08004513 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004514 return;
4515 }
4516 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4517 return;
4518 }
4519 }
4520 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4521 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4522 IActivityManager am = ActivityManagerNative.getDefault();
4523 if (am != null) {
4524 try {
4525 am.startService(null, intent, null);
4526 } catch (RemoteException e) {
4527 }
4528 }
4529 }
4530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 private final class AppDirObserver extends FileObserver {
4532 public AppDirObserver(String path, int mask, boolean isrom) {
4533 super(path, mask);
4534 mRootDir = path;
4535 mIsRom = isrom;
4536 }
4537
4538 public void onEvent(int event, String path) {
4539 String removedPackage = null;
4540 int removedUid = -1;
4541 String addedPackage = null;
4542 int addedUid = -1;
4543
Kenny Root447106f2011-03-23 11:00:15 -07004544 // TODO post a message to the handler to obtain serial ordering
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 synchronized (mInstallLock) {
4546 String fullPathStr = null;
4547 File fullPath = null;
4548 if (path != null) {
4549 fullPath = new File(mRootDir, path);
4550 fullPathStr = fullPath.getPath();
4551 }
4552
Kenny Root9718cf52011-02-23 16:45:26 -08004553 if (DEBUG_APP_DIR_OBSERVER)
4554 Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004555
4556 if (!isPackageFilename(path)) {
Kenny Root9718cf52011-02-23 16:45:26 -08004557 if (DEBUG_APP_DIR_OBSERVER)
4558 Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 return;
4560 }
4561
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004562 // Ignore packages that are being installed or
4563 // have just been installed.
4564 if (ignoreCodePath(fullPathStr)) {
4565 return;
4566 }
4567 PackageParser.Package p = null;
Kenny Root447106f2011-03-23 11:00:15 -07004568 // reader
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004569 synchronized (mPackages) {
4570 p = mAppDirs.get(fullPathStr);
4571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004573 if (p != null) {
4574 removePackageLI(p, true);
4575 removedPackage = p.applicationInfo.packageName;
4576 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 }
4578 }
4579
4580 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004582 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004583 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
4584 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 PackageParser.PARSE_CHATTY |
4586 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004587 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
4588 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004589 if (p != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004590 /*
4591 * TODO this seems dangerous as the package may have
4592 * changed since we last acquired the mPackages
4593 * lock.
4594 */
4595 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07004597 updatePermissionsLPw(p.packageName, p,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07004598 p.permissions.size() > 0, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 }
4600 addedPackage = p.applicationInfo.packageName;
4601 addedUid = p.applicationInfo.uid;
4602 }
4603 }
4604 }
4605
Kenny Root447106f2011-03-23 11:00:15 -07004606 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07004608 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004609 }
4610 }
4611
4612 if (removedPackage != null) {
4613 Bundle extras = new Bundle(1);
4614 extras.putInt(Intent.EXTRA_UID, removedUid);
4615 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004616 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004617 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 }
4619 if (addedPackage != null) {
4620 Bundle extras = new Bundle(1);
4621 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004622 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004623 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 }
4625 }
4626
4627 private final String mRootDir;
4628 private final boolean mIsRom;
4629 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 /* Called when a downloaded package installation has been confirmed by the user */
4632 public void installPackage(
4633 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004634 installPackage(packageURI, observer, flags, null);
4635 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004636
Jacek Surazski65e13172009-04-28 15:26:38 +02004637 /* Called when a downloaded package installation has been confirmed by the user */
4638 public void installPackage(
4639 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4640 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 mContext.enforceCallingOrSelfPermission(
4642 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004643
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004644 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004645 msg.obj = new InstallParams(packageURI, observer, flags,
4646 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004647 mHandler.sendMessage(msg);
4648 }
4649
Christopher Tate1bb69062010-02-19 17:02:12 -08004650 public void finishPackageInstall(int token) {
4651 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4652 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4653 mHandler.sendMessage(msg);
4654 }
4655
Kenny Rootf03b45f2011-02-23 17:25:45 -08004656 public void setInstallerPackageName(String targetPackage, String installerPackageName) {
Dianne Hackborn880119b2010-11-18 22:26:40 -08004657 final int uid = Binder.getCallingUid();
Kenny Root447106f2011-03-23 11:00:15 -07004658 // writer
Dianne Hackborn880119b2010-11-18 22:26:40 -08004659 synchronized (mPackages) {
4660 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
4661 if (targetPackageSetting == null) {
4662 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
4663 }
4664
4665 PackageSetting installerPackageSetting;
4666 if (installerPackageName != null) {
4667 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
4668 if (installerPackageSetting == null) {
4669 throw new IllegalArgumentException("Unknown installer package: "
4670 + installerPackageName);
4671 }
4672 } else {
4673 installerPackageSetting = null;
4674 }
4675
4676 Signature[] callerSignature;
Kenny Root447106f2011-03-23 11:00:15 -07004677 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborn880119b2010-11-18 22:26:40 -08004678 if (obj != null) {
4679 if (obj instanceof SharedUserSetting) {
4680 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
4681 } else if (obj instanceof PackageSetting) {
4682 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
4683 } else {
4684 throw new SecurityException("Bad object " + obj + " for uid " + uid);
4685 }
4686 } else {
4687 throw new SecurityException("Unknown calling uid " + uid);
4688 }
4689
4690 // Verify: can't set installerPackageName to a package that is
4691 // not signed with the same cert as the caller.
4692 if (installerPackageSetting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004693 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08004694 installerPackageSetting.signatures.mSignatures)
4695 != PackageManager.SIGNATURE_MATCH) {
4696 throw new SecurityException(
4697 "Caller does not have same cert as new installer package "
4698 + installerPackageName);
4699 }
4700 }
4701
4702 // Verify: if target already has an installer package, it must
4703 // be signed with the same cert as the caller.
4704 if (targetPackageSetting.installerPackageName != null) {
4705 PackageSetting setting = mSettings.mPackages.get(
4706 targetPackageSetting.installerPackageName);
4707 // If the currently set package isn't valid, then it's always
4708 // okay to change it.
4709 if (setting != null) {
Kenny Root447106f2011-03-23 11:00:15 -07004710 if (compareSignatures(callerSignature,
Dianne Hackborn880119b2010-11-18 22:26:40 -08004711 setting.signatures.mSignatures)
4712 != PackageManager.SIGNATURE_MATCH) {
4713 throw new SecurityException(
4714 "Caller does not have same cert as old installer package "
4715 + targetPackageSetting.installerPackageName);
4716 }
4717 }
4718 }
4719
4720 // Okay!
4721 targetPackageSetting.installerPackageName = installerPackageName;
4722 scheduleWriteSettingsLocked();
4723 }
4724 }
4725
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004726 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 // Queue up an async operation since the package installation may take a little while.
4728 mHandler.post(new Runnable() {
4729 public void run() {
4730 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004731 // Result object to be returned
4732 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004733 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004734 res.uid = -1;
4735 res.pkg = null;
4736 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004737 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004738 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004739 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004740 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004741 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004742 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004744
4745 // A restore should be performed at this point if (a) the install
4746 // succeeded, (b) the operation is not an update, and (c) the new
4747 // package has a backupAgent defined.
4748 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004749 boolean doRestore = (!update
4750 && res.pkg != null
4751 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004752
4753 // Set up the post-install work request bookkeeping. This will be used
4754 // and cleaned up by the post-install event handling regardless of whether
4755 // there's a restore pass performed. Token values are >= 1.
4756 int token;
4757 if (mNextInstallToken < 0) mNextInstallToken = 1;
4758 token = mNextInstallToken++;
4759
4760 PostInstallData data = new PostInstallData(args, res);
4761 mRunningInstalls.put(token, data);
4762 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4763
4764 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4765 // Pass responsibility to the Backup Manager. It will perform a
4766 // restore if appropriate, then pass responsibility back to the
4767 // Package Manager to run the post-install observer callbacks
4768 // and broadcasts.
4769 IBackupManager bm = IBackupManager.Stub.asInterface(
4770 ServiceManager.getService(Context.BACKUP_SERVICE));
4771 if (bm != null) {
4772 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4773 + " to BM for possible restore");
4774 try {
4775 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4776 } catch (RemoteException e) {
4777 // can't happen; the backup manager is local
4778 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004779 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08004780 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004781 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004782 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004783 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08004784 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004787
4788 if (!doRestore) {
4789 // No restore possible, or the Backup Manager was mysteriously not
4790 // available -- just fire the post-install work request directly.
4791 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4792 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4793 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795 }
4796 });
4797 }
4798
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004799 abstract class HandlerParams {
4800 final static int MAX_RETRIES = 4;
4801 int retry = 0;
4802 final void startCopy() {
4803 try {
4804 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
4805 retry++;
4806 if (retry > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004807 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004808 mHandler.sendEmptyMessage(MCS_GIVE_UP);
4809 handleServiceError();
4810 return;
4811 } else {
4812 handleStartCopy();
4813 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
4814 mHandler.sendEmptyMessage(MCS_UNBIND);
4815 }
4816 } catch (RemoteException e) {
4817 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
4818 mHandler.sendEmptyMessage(MCS_RECONNECT);
4819 }
4820 handleReturnCode();
4821 }
4822
4823 final void serviceError() {
4824 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
4825 handleServiceError();
4826 handleReturnCode();
4827 }
4828 abstract void handleStartCopy() throws RemoteException;
4829 abstract void handleServiceError();
4830 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004831 }
4832
Kenny Root366949c2011-01-14 17:18:14 -08004833 class MeasureParams extends HandlerParams {
4834 private final PackageStats mStats;
4835 private boolean mSuccess;
4836
4837 private final IPackageStatsObserver mObserver;
4838
4839 public MeasureParams(PackageStats stats, boolean success,
4840 IPackageStatsObserver observer) {
4841 mObserver = observer;
4842 mStats = stats;
4843 mSuccess = success;
4844 }
4845
4846 @Override
4847 void handleStartCopy() throws RemoteException {
4848 final boolean mounted;
4849
4850 if (Environment.isExternalStorageEmulated()) {
4851 mounted = true;
4852 } else {
4853 final String status = Environment.getExternalStorageState();
4854
4855 mounted = status.equals(Environment.MEDIA_MOUNTED)
4856 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
4857 }
4858
4859 if (mounted) {
4860 final File externalCacheDir = Environment
4861 .getExternalStorageAppCacheDirectory(mStats.packageName);
4862 final long externalCacheSize = mContainerService
4863 .calculateDirectorySize(externalCacheDir.getPath());
4864 mStats.externalCacheSize = externalCacheSize;
4865
4866 final File externalDataDir = Environment
4867 .getExternalStorageAppDataDirectory(mStats.packageName);
4868 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
4869 .getPath());
4870
4871 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
4872 externalDataSize -= externalCacheSize;
4873 }
4874 mStats.externalDataSize = externalDataSize;
4875
4876 final File externalMediaDir = Environment
4877 .getExternalStorageAppMediaDirectory(mStats.packageName);
4878 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08004879 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08004880
4881 final File externalObbDir = Environment
4882 .getExternalStorageAppObbDirectory(mStats.packageName);
4883 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
4884 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08004885 }
4886 }
4887
4888 @Override
4889 void handleReturnCode() {
4890 if (mObserver != null) {
4891 try {
4892 mObserver.onGetStatsCompleted(mStats, mSuccess);
4893 } catch (RemoteException e) {
4894 Slog.i(TAG, "Observer no longer exists.");
4895 }
4896 }
4897 }
4898
4899 @Override
4900 void handleServiceError() {
4901 Slog.e(TAG, "Could not measure application " + mStats.packageName
4902 + " external storage");
4903 }
4904 }
4905
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004906 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004907 final IPackageInstallObserver observer;
4908 int flags;
4909 final Uri packageURI;
4910 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004911 private InstallArgs mArgs;
4912 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004913 InstallParams(Uri packageURI,
4914 IPackageInstallObserver observer, int flags,
4915 String installerPackageName) {
4916 this.packageURI = packageURI;
4917 this.flags = flags;
4918 this.observer = observer;
4919 this.installerPackageName = installerPackageName;
4920 }
4921
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004922 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
4923 String packageName = pkgLite.packageName;
4924 int installLocation = pkgLite.installLocation;
4925 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Kenny Root447106f2011-03-23 11:00:15 -07004926 // reader
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004927 synchronized (mPackages) {
4928 PackageParser.Package pkg = mPackages.get(packageName);
4929 if (pkg != null) {
4930 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
4931 // Check for updated system application.
4932 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4933 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004934 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004935 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
4936 }
4937 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4938 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004939 if (onSd) {
4940 // Install flag overrides everything.
4941 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4942 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004943 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004944 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
4945 // Application explicitly specified internal.
4946 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4947 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
4948 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004949 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004950 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07004951 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004952 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4953 }
4954 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004955 }
4956 }
4957 } else {
4958 // Invalid install. Return error code
4959 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
4960 }
4961 }
4962 }
4963 // All the special cases have been taken care of.
4964 // Return result based on recommended install location.
4965 if (onSd) {
4966 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4967 }
4968 return pkgLite.recommendedInstallLocation;
4969 }
4970
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004971 /*
4972 * Invoke remote method to get package information and install
4973 * location values. Override install location based on default
4974 * policy if needed and then create install arguments based
4975 * on the install location.
4976 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004977 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004978 int ret = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004979 boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
4980 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004981 boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
4982 if (onInt && onSd) {
4983 // Check if both bits are set.
4984 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
4985 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4986 } else if (fwdLocked && onSd) {
4987 // Check for forward locked apps
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004988 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004989 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004990 } else {
Kenny Root62e1b4e2011-03-14 17:13:39 -07004991 final long lowThreshold;
4992
4993 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
4994 .getService(DeviceStorageMonitorService.SERVICE);
4995 if (dsm == null) {
4996 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
4997 lowThreshold = 0L;
4998 } else {
4999 lowThreshold = dsm.getMemoryLowThreshold();
5000 }
5001
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005002 // Remote call to find out default install location
Kenny Root11128572010-10-11 10:51:32 -07005003 final PackageInfoLite pkgLite;
5004 try {
5005 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5006 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root62e1b4e2011-03-14 17:13:39 -07005007 pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags,
5008 lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07005009 } finally {
5010 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5011 }
5012
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005013 int loc = pkgLite.recommendedInstallLocation;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08005014 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
5015 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5016 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
5017 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5018 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005019 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5020 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
5021 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005022 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
5023 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005024 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005025 // Override with defaults if needed.
5026 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005027 if (!onSd && !onInt) {
5028 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005029 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
5030 // Set the flag to install on external media.
5031 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005032 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005033 } else {
5034 // Make sure the flag for installing on external
5035 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07005036 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005037 flags &= ~PackageManager.INSTALL_EXTERNAL;
5038 }
5039 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005040 }
5041 }
5042 // Create the file args now.
5043 mArgs = createInstallArgs(this);
5044 if (ret == PackageManager.INSTALL_SUCCEEDED) {
5045 // Create copy only if we are not in an erroneous state.
5046 // Remote call to initiate copy using temporary file
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005047 ret = mArgs.copyApk(mContainerService, true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005048 }
5049 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005050 }
5051
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005052 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005053 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07005054 // If mArgs is null, then MCS couldn't be reached. When it
5055 // reconnects, it will try again to install. At that point, this
5056 // will succeed.
5057 if (mArgs != null) {
5058 processPendingInstall(mArgs, mRet);
5059 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005060 }
5061
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005062 @Override
5063 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005064 mArgs = createInstallArgs(this);
5065 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005066 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005067 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005068
5069 /*
5070 * Utility class used in movePackage api.
5071 * srcArgs and targetArgs are not set for invalid flags and make
5072 * sure to do null checks when invoking methods on them.
5073 * We probably want to return ErrorPrams for both failed installs
5074 * and moves.
5075 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005076 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005077 final IPackageMoveObserver observer;
5078 final int flags;
5079 final String packageName;
5080 final InstallArgs srcArgs;
5081 final InstallArgs targetArgs;
5082 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07005083
5084 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
5085 String packageName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005086 this.srcArgs = srcArgs;
5087 this.observer = observer;
5088 this.flags = flags;
5089 this.packageName = packageName;
5090 if (srcArgs != null) {
5091 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07005092 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005093 } else {
5094 targetArgs = null;
5095 }
5096 }
5097
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005098 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005099 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5100 // Check for storage space on target medium
5101 if (!targetArgs.checkFreeStorage(mContainerService)) {
5102 Log.w(TAG, "Insufficient storage to install");
5103 return;
5104 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005105 // Create the file args now.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005106 mRet = targetArgs.copyApk(mContainerService, false);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005107 targetArgs.doPreInstall(mRet);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005108 if (DEBUG_SD_INSTALL) {
5109 StringBuilder builder = new StringBuilder();
5110 if (srcArgs != null) {
5111 builder.append("src: ");
5112 builder.append(srcArgs.getCodePath());
5113 }
5114 if (targetArgs != null) {
5115 builder.append(" target : ");
5116 builder.append(targetArgs.getCodePath());
5117 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005118 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005119 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005120 }
5121
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005122 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005123 void handleReturnCode() {
5124 targetArgs.doPostInstall(mRet);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005125 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
5126 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
5127 currentStatus = PackageManager.MOVE_SUCCEEDED;
5128 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
5129 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
5130 }
5131 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005132 }
5133
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005134 @Override
5135 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005136 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005137 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005138 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005139
5140 private InstallArgs createInstallArgs(InstallParams params) {
5141 if (installOnSd(params.flags)) {
5142 return new SdInstallArgs(params);
5143 } else {
5144 return new FileInstallArgs(params);
5145 }
5146 }
5147
Kenny Root85387d72010-08-26 10:13:11 -07005148 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
5149 String nativeLibraryPath) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005150 if (installOnSd(flags)) {
Kenny Root85387d72010-08-26 10:13:11 -07005151 return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005152 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005153 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005154 }
5155 }
5156
Kenny Root85387d72010-08-26 10:13:11 -07005157 // Used by package mover
5158 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005159 if (installOnSd(flags)) {
5160 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
5161 return new SdInstallArgs(packageURI, cid);
5162 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005163 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005164 }
5165 }
5166
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005167 static abstract class InstallArgs {
5168 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005169 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005170 final int flags;
5171 final Uri packageURI;
5172 final String installerPackageName;
5173
5174 InstallArgs(Uri packageURI,
5175 IPackageInstallObserver observer, int flags,
5176 String installerPackageName) {
5177 this.packageURI = packageURI;
5178 this.flags = flags;
5179 this.observer = observer;
5180 this.installerPackageName = installerPackageName;
5181 }
5182
5183 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005184 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005185 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005186 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005187 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005188 abstract String getCodePath();
5189 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07005190 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005191 // Need installer lock especially for dex file removal.
5192 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005193 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005194 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005195 }
5196
5197 class FileInstallArgs extends InstallArgs {
5198 File installDir;
5199 String codeFileName;
5200 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07005201 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005202 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005203
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005204 FileInstallArgs(InstallParams params) {
5205 super(params.packageURI, params.observer,
5206 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005207 }
5208
Kenny Root85387d72010-08-26 10:13:11 -07005209 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005210 super(null, null, 0, null);
5211 File codeFile = new File(fullCodePath);
5212 installDir = codeFile.getParentFile();
5213 codeFileName = fullCodePath;
5214 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07005215 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005216 }
5217
Kenny Root85387d72010-08-26 10:13:11 -07005218 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005219 super(packageURI, null, 0, null);
Kenny Root85387d72010-08-26 10:13:11 -07005220 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005221 String apkName = getNextCodePath(null, pkgName, ".apk");
5222 codeFileName = new File(installDir, apkName + ".apk").getPath();
5223 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07005224 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005225 }
5226
Kenny Root11128572010-10-11 10:51:32 -07005227 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
Kenny Root62e1b4e2011-03-14 17:13:39 -07005228 final long lowThreshold;
5229
5230 final DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) ServiceManager
5231 .getService(DeviceStorageMonitorService.SERVICE);
5232 if (dsm == null) {
5233 Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
5234 lowThreshold = 0L;
5235 } else {
5236 if (dsm.isMemoryLow()) {
5237 Log.w(TAG, "Memory is reported as being too low; aborting package install");
5238 return false;
5239 }
5240
5241 lowThreshold = dsm.getMemoryLowThreshold();
5242 }
5243
Kenny Root11128572010-10-11 10:51:32 -07005244 try {
5245 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5246 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root62e1b4e2011-03-14 17:13:39 -07005247 return imcs.checkInternalFreeStorage(packageURI, lowThreshold);
Kenny Root11128572010-10-11 10:51:32 -07005248 } finally {
5249 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5250 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005251 }
5252
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005253 String getCodePath() {
5254 return codeFileName;
5255 }
5256
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005257 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07005258 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005259 codeFileName = createTempPackageFile(installDir).getPath();
5260 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005261 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005262 }
5263
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005264 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005265 if (temp) {
5266 // Generate temp file name
5267 createCopyFile();
5268 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005269 // Get a ParcelFileDescriptor to write to the output file
5270 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005271 if (!created) {
5272 try {
5273 codeFile.createNewFile();
5274 // Set permissions
5275 if (!setPermissions()) {
5276 // Failed setting permissions.
5277 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5278 }
5279 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005280 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005281 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5282 }
5283 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005284 ParcelFileDescriptor out = null;
5285 try {
Kenny Root85387d72010-08-26 10:13:11 -07005286 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005287 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005288 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005289 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5290 }
5291 // Copy the resource now
5292 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5293 try {
Kenny Root11128572010-10-11 10:51:32 -07005294 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5295 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005296 if (imcs.copyResource(packageURI, out)) {
5297 ret = PackageManager.INSTALL_SUCCEEDED;
5298 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005299 } finally {
5300 try { if (out != null) out.close(); } catch (IOException e) {}
Kenny Root11128572010-10-11 10:51:32 -07005301 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005302 }
Kenny Root85387d72010-08-26 10:13:11 -07005303
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005304 return ret;
5305 }
5306
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005307 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005308 if (status != PackageManager.INSTALL_SUCCEEDED) {
5309 cleanUp();
5310 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005311 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005312 }
5313
5314 boolean doRename(int status, final String pkgName, String oldCodePath) {
5315 if (status != PackageManager.INSTALL_SUCCEEDED) {
5316 cleanUp();
5317 return false;
5318 } else {
5319 // Rename based on packageName
5320 File codeFile = new File(getCodePath());
5321 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
5322 File desFile = new File(installDir, apkName + ".apk");
5323 if (!codeFile.renameTo(desFile)) {
5324 return false;
5325 }
5326 // Reset paths since the file has been renamed.
5327 codeFileName = desFile.getPath();
5328 resourceFileName = getResourcePathFromCodePath();
5329 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005330 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005331 // Failed setting permissions.
5332 return false;
5333 }
5334 return true;
5335 }
5336 }
5337
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005338 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005339 if (status != PackageManager.INSTALL_SUCCEEDED) {
5340 cleanUp();
5341 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005342 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005343 }
5344
5345 String getResourcePath() {
5346 return resourceFileName;
5347 }
5348
5349 String getResourcePathFromCodePath() {
5350 String codePath = getCodePath();
5351 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
5352 String apkNameOnly = getApkName(codePath);
5353 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
5354 } else {
5355 return codePath;
5356 }
5357 }
5358
Kenny Root85387d72010-08-26 10:13:11 -07005359 @Override
5360 String getNativeLibraryPath() {
5361 return libraryPath;
5362 }
5363
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005364 private boolean cleanUp() {
5365 boolean ret = true;
5366 String sourceDir = getCodePath();
5367 String publicSourceDir = getResourcePath();
5368 if (sourceDir != null) {
5369 File sourceFile = new File(sourceDir);
5370 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005371 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005372 ret = false;
5373 }
5374 // Delete application's code and resources
5375 sourceFile.delete();
5376 }
5377 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
5378 final File publicSourceFile = new File(publicSourceDir);
5379 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005380 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005381 }
5382 if (publicSourceFile.exists()) {
5383 publicSourceFile.delete();
5384 }
5385 }
5386 return ret;
5387 }
5388
5389 void cleanUpResourcesLI() {
5390 String sourceDir = getCodePath();
5391 if (cleanUp() && mInstaller != null) {
5392 int retCode = mInstaller.rmdex(sourceDir);
5393 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005394 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005395 + " at location "
5396 + sourceDir + ", retcode=" + retCode);
5397 // we don't consider this to be a failure of the core package deletion
5398 }
5399 }
5400 }
5401
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005402 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005403 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07005404 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005405 final int filePermissions =
5406 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
5407 |FileUtils.S_IROTH;
5408 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
5409 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005410 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005411 getCodePath()
5412 + ". The return code was: " + retCode);
5413 // TODO Define new internal error
5414 return false;
5415 }
5416 return true;
5417 }
5418 return true;
5419 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005420
5421 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07005422 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005423 cleanUpResourcesLI();
5424 return true;
5425 }
Kenny Root85387d72010-08-26 10:13:11 -07005426
5427 private boolean isFwdLocked() {
5428 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5429 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005430 }
5431
5432 class SdInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005433 static final String RES_FILE_NAME = "pkg.apk";
5434
Kenny Root85387d72010-08-26 10:13:11 -07005435 String cid;
5436 String packagePath;
5437 String libraryPath;
5438
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005439 SdInstallArgs(InstallParams params) {
5440 super(params.packageURI, params.observer,
5441 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005442 }
5443
Kenny Root85387d72010-08-26 10:13:11 -07005444 SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005445 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005446 // Extract cid from fullCodePath
5447 int eidx = fullCodePath.lastIndexOf("/");
5448 String subStr1 = fullCodePath.substring(0, eidx);
5449 int sidx = subStr1.lastIndexOf("/");
5450 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07005451 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005452 }
5453
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005454 SdInstallArgs(String cid) {
Dianne Hackbornaa77de12010-05-14 22:33:54 -07005455 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
5456 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07005457 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005458 }
5459
5460 SdInstallArgs(Uri packageURI, String cid) {
5461 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005462 this.cid = cid;
5463 }
5464
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005465 void createCopyFile() {
5466 cid = getTempContainerId();
5467 }
5468
Kenny Root11128572010-10-11 10:51:32 -07005469 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5470 try {
5471 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5472 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Kenny Root62e1b4e2011-03-14 17:13:39 -07005473 return imcs.checkExternalFreeStorage(packageURI);
Kenny Root11128572010-10-11 10:51:32 -07005474 } finally {
5475 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5476 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005477 }
5478
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005479 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005480 if (temp) {
5481 createCopyFile();
5482 }
Kenny Root11128572010-10-11 10:51:32 -07005483
5484 final String newCachePath;
5485 try {
5486 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5487 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5488 newCachePath = imcs.copyResourceToContainer(packageURI, cid,
5489 getEncryptKey(), RES_FILE_NAME);
5490 } finally {
5491 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5492 }
5493
Kenny Root85387d72010-08-26 10:13:11 -07005494 if (newCachePath != null) {
5495 setCachePath(newCachePath);
5496 return PackageManager.INSTALL_SUCCEEDED;
5497 } else {
5498 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5499 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005500 }
5501
5502 @Override
5503 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005504 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005505 }
5506
5507 @Override
5508 String getResourcePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005509 return packagePath;
5510 }
5511
5512 @Override
5513 String getNativeLibraryPath() {
5514 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005515 }
5516
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005517 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005518 if (status != PackageManager.INSTALL_SUCCEEDED) {
5519 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005520 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005521 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005522 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005523 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07005524 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
5525 Process.SYSTEM_UID);
5526 if (newCachePath != null) {
5527 setCachePath(newCachePath);
5528 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005529 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5530 }
5531 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005532 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005533 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005534 }
5535
5536 boolean doRename(int status, final String pkgName,
5537 String oldCodePath) {
5538 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005539 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005540 if (PackageHelper.isContainerMounted(cid)) {
5541 // Unmount the container
5542 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005543 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005544 return false;
5545 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005546 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005547 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07005548 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
5549 " which might be stale. Will try to clean up.");
5550 // Clean up the stale container and proceed to recreate.
5551 if (!PackageHelper.destroySdDir(newCacheId)) {
5552 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
5553 return false;
5554 }
5555 // Successfully cleaned up stale container. Try to rename again.
5556 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
5557 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
5558 + " inspite of cleaning it up.");
5559 return false;
5560 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005561 }
5562 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005563 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005564 newCachePath = PackageHelper.mountSdDir(newCacheId,
5565 getEncryptKey(), Process.SYSTEM_UID);
5566 } else {
5567 newCachePath = PackageHelper.getSdDir(newCacheId);
5568 }
5569 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005570 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005571 return false;
5572 }
5573 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07005574 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005575 " at new path: " + newCachePath);
5576 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07005577 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005578 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005579 }
5580
Kenny Root85387d72010-08-26 10:13:11 -07005581 private void setCachePath(String newCachePath) {
5582 File cachePath = new File(newCachePath);
5583 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
5584 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
5585 }
5586
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005587 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005588 if (status != PackageManager.INSTALL_SUCCEEDED) {
5589 cleanUp();
5590 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005591 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005592 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005593 PackageHelper.mountSdDir(cid,
5594 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005595 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005596 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005597 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005598 }
5599
5600 private void cleanUp() {
5601 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005602 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005603 }
5604
5605 void cleanUpResourcesLI() {
5606 String sourceFile = getCodePath();
5607 // Remove dex file
5608 if (mInstaller != null) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005609 int retCode = mInstaller.rmdex(sourceFile);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005610 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005611 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005612 + " at location "
5613 + sourceFile.toString() + ", retcode=" + retCode);
5614 // we don't consider this to be a failure of the core package deletion
5615 }
5616 }
5617 cleanUp();
5618 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005619
5620 boolean matchContainer(String app) {
5621 if (cid.startsWith(app)) {
5622 return true;
5623 }
5624 return false;
5625 }
5626
5627 String getPackageName() {
5628 int idx = cid.lastIndexOf("-");
5629 if (idx == -1) {
5630 return cid;
5631 }
5632 return cid.substring(0, idx);
5633 }
5634
5635 boolean doPostDeleteLI(boolean delete) {
5636 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005637 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005638 if (mounted) {
5639 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005640 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005641 }
5642 if (ret && delete) {
5643 cleanUpResourcesLI();
5644 }
5645 return ret;
5646 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005647 };
5648
5649 // Utility method used to create code paths based on package name and available index.
5650 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
5651 String idxStr = "";
5652 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005653 // Fall back to default value of idx=1 if prefix is not
5654 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005655 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005656 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005657 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005658 if (subStr.endsWith(suffix)) {
5659 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005660 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005661 // If oldCodePath already contains prefix find out the
5662 // ending index to either increment or decrement.
5663 int sidx = subStr.lastIndexOf(prefix);
5664 if (sidx != -1) {
5665 subStr = subStr.substring(sidx + prefix.length());
5666 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005667 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5668 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005669 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005670 try {
5671 idx = Integer.parseInt(subStr);
5672 if (idx <= 1) {
5673 idx++;
5674 } else {
5675 idx--;
5676 }
5677 } catch(NumberFormatException e) {
5678 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005679 }
5680 }
5681 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005682 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005683 return prefix + idxStr;
5684 }
5685
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005686 // Utility method used to ignore ADD/REMOVE events
5687 // by directory observer.
5688 private static boolean ignoreCodePath(String fullPathStr) {
5689 String apkName = getApkName(fullPathStr);
5690 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5691 if (idx != -1 && ((idx+1) < apkName.length())) {
5692 // Make sure the package ends with a numeral
5693 String version = apkName.substring(idx+1);
5694 try {
5695 Integer.parseInt(version);
5696 return true;
5697 } catch (NumberFormatException e) {}
5698 }
5699 return false;
5700 }
5701
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005702 // Utility method that returns the relative package path with respect
5703 // to the installation directory. Like say for /data/data/com.test-1.apk
5704 // string com.test-1 is returned.
5705 static String getApkName(String codePath) {
5706 if (codePath == null) {
5707 return null;
5708 }
5709 int sidx = codePath.lastIndexOf("/");
5710 int eidx = codePath.lastIndexOf(".");
5711 if (eidx == -1) {
5712 eidx = codePath.length();
5713 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005714 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005715 return null;
5716 }
5717 return codePath.substring(sidx+1, eidx);
5718 }
5719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 class PackageInstalledInfo {
5721 String name;
5722 int uid;
5723 PackageParser.Package pkg;
5724 int returnCode;
5725 PackageRemovedInfo removedInfo;
5726 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005728 /*
5729 * Install a non-existing package.
5730 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005731 private void installNewPackageLI(PackageParser.Package pkg,
5732 int parseFlags,
5733 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005734 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005736 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005737
Amith Yamasani0b285492011-04-14 17:35:23 -07005738 boolean dataDirExists = getDataPathForPackage(pkg.packageName, 0).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739 res.name = pkgName;
5740 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07005741 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
5742 // A package with the same name is already installed, though
5743 // it has been renamed to an older name. The package we
5744 // are trying to install should be installed as an update to
5745 // the existing one, but that has not been requested, so bail.
5746 Slog.w(TAG, "Attempt to re-install " + pkgName
5747 + " without first uninstalling package running as "
5748 + mSettings.mRenamedPackages.get(pkgName));
5749 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5750 return;
5751 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005752 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005754 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 + " without first uninstalling.");
5756 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5757 return;
5758 }
5759 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005761 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
5762 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005763 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005764 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5766 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5767 }
5768 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005769 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005770 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 res);
5772 // delete the partially installed application. the data directory will have to be
5773 // restored if it was already existing
5774 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5775 // remove package from internal structures. Note that we want deletePackageX to
5776 // delete the package data and cache directories that it created in
5777 // scanPackageLocked, unless those directories existed before we even tried to
5778 // install.
5779 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005780 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005782 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005783 }
5784 }
5785 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005786
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005787 private void replacePackageLI(PackageParser.Package pkg,
5788 int parseFlags,
5789 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005790 String installerPackageName, PackageInstalledInfo res) {
5791
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005792 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005793 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 // First find the old package info and check signatures
5795 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005796 oldPackage = mPackages.get(pkgName);
Kenny Root447106f2011-03-23 11:00:15 -07005797 if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005798 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5800 return;
5801 }
5802 }
Kenny Root85387d72010-08-26 10:13:11 -07005803 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005804 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005805 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005807 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 }
5809 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005812 PackageParser.Package pkg,
5813 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005814 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 PackageParser.Package newPackage = null;
5816 String pkgName = deletedPackage.packageName;
5817 boolean deletedPkg = true;
5818 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005819
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005820 long origUpdateTime;
5821 if (pkg.mExtras != null) {
5822 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
5823 } else {
5824 origUpdateTime = 0;
5825 }
5826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005828 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005829 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005830 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5832 deletedPkg = false;
5833 } else {
5834 // Successfully deleted the old package. Now proceed with re-installation
5835 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005836 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
5837 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005839 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5841 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005842 }
5843 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005844 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005845 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005846 res);
5847 updatedSettings = true;
5848 }
5849 }
5850
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005851 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 // remove package from internal structures. Note that we want deletePackageX to
5853 // delete the package data and cache directories that it created in
5854 // scanPackageLocked, unless those directories existed before we even tried to
5855 // install.
5856 if(updatedSettings) {
5857 deletePackageLI(
5858 pkgName, true,
5859 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005860 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 }
5862 // Since we failed to install the new package we need to restore the old
5863 // package that we deleted.
5864 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005865 File restoreFile = new File(deletedPackage.mPath);
5866 if (restoreFile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005867 Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005868 return;
5869 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005870 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005871 boolean oldOnSd = isExternal(deletedPackage);
5872 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
5873 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5874 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005875 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
5876 | SCAN_UPDATE_TIME;
5877 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
5878 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005879 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
5880 return;
5881 }
5882 // Restore of old package succeeded. Update permissions.
Kenny Root447106f2011-03-23 11:00:15 -07005883 // writer
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005884 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005885 updatePermissionsLPw(deletedPackage.packageName, deletedPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07005886 true, false, false);
Kenny Root447106f2011-03-23 11:00:15 -07005887 // can downgrade to reader
5888 mSettings.writeLPr();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005889 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005890 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 }
5892 }
5893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005896 PackageParser.Package pkg,
5897 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005898 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 PackageParser.Package newPackage = null;
5900 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005901 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 PackageParser.PARSE_IS_SYSTEM;
5903 String packageName = deletedPackage.packageName;
5904 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5905 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005906 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 return;
5908 }
5909 PackageParser.Package oldPkg;
5910 PackageSetting oldPkgSetting;
Kenny Root447106f2011-03-23 11:00:15 -07005911 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 synchronized (mPackages) {
5913 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005914 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5916 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005917 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 return;
5919 }
5920 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005921
5922 killApplication(packageName, oldPkg.applicationInfo.uid);
5923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5925 res.removedInfo.removedPackage = packageName;
5926 // Remove existing system package
5927 removePackageLI(oldPkg, true);
Kenny Root447106f2011-03-23 11:00:15 -07005928 // writer
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005929 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07005930 if (!mSettings.disableSystemPackageLPw(packageName) && deletedPackage != null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005931 // We didn't need to disable the .apk as a current system package,
5932 // which means we are replacing another update that is already
5933 // installed. We need to make sure to delete the older one's .apk.
5934 res.removedInfo.args = createInstallArgs(isExternal(pkg)
5935 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
5936 deletedPackage.applicationInfo.sourceDir,
5937 deletedPackage.applicationInfo.publicSourceDir,
5938 deletedPackage.applicationInfo.nativeLibraryDir);
5939 } else {
5940 res.removedInfo.args = null;
5941 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005942 }
5943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944 // Successfully disabled the old package. Now proceed with re-installation
5945 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5946 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005947 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005949 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5951 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5952 }
5953 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005954 if (newPackage.mExtras != null) {
5955 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
5956 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
5957 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
5958 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005959 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 updatedSettings = true;
5961 }
5962
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005963 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 // Re installation failed. Restore old information
5965 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005966 if (newPackage != null) {
5967 removePackageLI(newPackage, true);
5968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005970 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 // Restore the old system information in Settings
5972 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005973 if (updatedSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07005974 mSettings.enableSystemPackageLPw(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005975 mSettings.setInstallerPackageName(packageName,
5976 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005977 }
Kenny Root447106f2011-03-23 11:00:15 -07005978 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
5980 }
5981 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005982
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005983 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005984 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005985 int retCode;
5986 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5987 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5988 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07005989 if (mNoDexOpt) {
5990 /*
5991 * If we're in an engineering build, programs are lazily run
5992 * through dexopt. If the .dex file doesn't exist yet, it
5993 * will be created when the program is run next.
5994 */
5995 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
5996 } else {
5997 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
5998 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5999 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006000 }
6001 }
6002 return PackageManager.INSTALL_SUCCEEDED;
6003 }
6004
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006005 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02006006 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006007 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 synchronized (mPackages) {
6009 //write settings. the installStatus will be incomplete at this stage.
6010 //note that the new package setting would have already been
6011 //added to mPackages. It hasn't been persisted yet.
Kenny Rootcf0b38c2011-03-22 14:17:59 -07006012 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_INCOMPLETE);
Kenny Root447106f2011-03-23 11:00:15 -07006013 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 }
6015
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07006016 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006017 != PackageManager.INSTALL_SUCCEEDED) {
6018 // Discontinue if moving dex files failed.
6019 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08006021 if((res.returnCode = setPermissionsLI(newPackage))
6022 != PackageManager.INSTALL_SUCCEEDED) {
6023 if (mInstaller != null) {
6024 mInstaller.rmdex(newPackage.mScanPath);
6025 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006026 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006028 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006031 updatePermissionsLPw(newPackage.packageName, newPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07006032 newPackage.permissions.size() > 0, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 res.name = pkgName;
6034 res.uid = newPackage.applicationInfo.uid;
6035 res.pkg = newPackage;
Kenny Rootcf0b38c2011-03-22 14:17:59 -07006036 mSettings.setInstallStatus(pkgName, PackageSettingBase.PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02006037 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6039 //to update install status
Kenny Root447106f2011-03-23 11:00:15 -07006040 mSettings.writeLPr();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 }
6042 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006043
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006044 private void installPackageLI(InstallArgs args,
6045 boolean newInstall, PackageInstalledInfo res) {
6046 int pFlags = args.flags;
6047 String installerPackageName = args.installerPackageName;
6048 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006049 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006050 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006051 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006052 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006053 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07006054 // Result object to be returned
6055 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
6056
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006057 // Retrieve PackageSettings and parse package
6058 int parseFlags = PackageParser.PARSE_CHATTY |
6059 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
6060 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
6061 parseFlags |= mDefParseFlags;
6062 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
6063 pp.setSeparateProcesses(mSeparateProcesses);
6064 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
6065 null, mMetrics, parseFlags);
6066 if (pkg == null) {
6067 res.returnCode = pp.getParseError();
6068 return;
6069 }
6070 String pkgName = res.name = pkg.packageName;
6071 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
6072 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
6073 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
6074 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006076 }
6077 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
6078 res.returnCode = pp.getParseError();
6079 return;
6080 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006081 // Get rid of all references to package scan path via parser.
6082 pp = null;
6083 String oldCodePath = null;
6084 boolean systemApp = false;
6085 synchronized (mPackages) {
6086 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006087 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
6088 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08006089 if (pkg.mOriginalPackages != null
6090 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006091 && mPackages.containsKey(oldName)) {
6092 // This package is derived from an original package,
6093 // and this device has been updating from that original
6094 // name. We must continue using the original name, so
6095 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08006096 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006097 pkgName = pkg.packageName;
6098 replace = true;
6099 } else if (mPackages.containsKey(pkgName)) {
6100 // This package, under its official name, already exists
6101 // on the device; we should replace it.
6102 replace = true;
6103 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006104 }
6105 PackageSetting ps = mSettings.mPackages.get(pkgName);
6106 if (ps != null) {
6107 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
6108 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
6109 systemApp = (ps.pkg.applicationInfo.flags &
6110 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07006111 }
6112 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006114
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006115 if (systemApp && onSd) {
6116 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006117 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006118 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
6119 return;
6120 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08006121
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006122 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
6123 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6124 return;
6125 }
6126 // Set application objects path explicitly after the rename
6127 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07006128 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006129 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006130 replacePackageLI(pkg, parseFlags, scanMode,
6131 installerPackageName, res);
6132 } else {
6133 installNewPackageLI(pkg, parseFlags, scanMode,
6134 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 }
6136 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006137
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006138 private int setPermissionsLI(PackageParser.Package newPackage) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006139 int retCode = 0;
6140 // TODO Gross hack but fix later. Ideally move this to be a post installation
6141 // check after alloting uid.
Kenny Root85387d72010-08-26 10:13:11 -07006142 if (isForwardLocked(newPackage)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006143 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 try {
6145 extractPublicFiles(newPackage, destResourceFile);
6146 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006147 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 " forward-locked app.");
6149 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6150 } finally {
6151 //TODO clean up the extracted public files
6152 }
6153 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006154 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 newPackage.applicationInfo.uid);
6156 } else {
6157 final int filePermissions =
6158 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006159 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 newPackage.applicationInfo.uid);
6161 }
6162 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006163 // The permissions on the resource file was set when it was copied for
6164 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006165 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 if (retCode != 0) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08006168 Slog.e(TAG, "Couldn't set new package file permissions for " + newPackage.mPath
6169 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006170 // TODO Define new internal error
6171 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006172 }
6173 return PackageManager.INSTALL_SUCCEEDED;
6174 }
6175
Kenny Root85387d72010-08-26 10:13:11 -07006176 private static boolean isForwardLocked(PackageParser.Package pkg) {
6177 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 }
6179
Kenny Root85387d72010-08-26 10:13:11 -07006180 private static boolean isExternal(PackageParser.Package pkg) {
6181 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
6182 }
6183
6184 private static boolean isSystemApp(PackageParser.Package pkg) {
6185 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6186 }
6187
Kenny Root502e9a42011-01-10 13:48:15 -08006188 private static boolean isSystemApp(ApplicationInfo info) {
6189 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6190 }
6191
Kenny Root85387d72010-08-26 10:13:11 -07006192 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
6193 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006194 }
6195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 private void extractPublicFiles(PackageParser.Package newPackage,
6197 File publicZipFile) throws IOException {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006198 final FileOutputStream fstr = new FileOutputStream(publicZipFile);
6199 final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 final ZipFile privateZip = new ZipFile(newPackage.mPath);
6201
6202 // Copy manifest, resources.arsc and res directory to public zip
6203
6204 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
6205 while (privateZipEntries.hasMoreElements()) {
6206 final ZipEntry zipEntry = privateZipEntries.nextElement();
6207 final String zipEntryName = zipEntry.getName();
6208 if ("AndroidManifest.xml".equals(zipEntryName)
6209 || "resources.arsc".equals(zipEntryName)
6210 || zipEntryName.startsWith("res/")) {
6211 try {
6212 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
6213 } catch (IOException e) {
6214 try {
6215 publicZipOutStream.close();
6216 throw e;
6217 } finally {
6218 publicZipFile.delete();
6219 }
6220 }
6221 }
6222 }
6223
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006224 publicZipOutStream.finish();
6225 publicZipOutStream.flush();
6226 FileUtils.sync(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 publicZipOutStream.close();
6228 FileUtils.setPermissions(
6229 publicZipFile.getAbsolutePath(),
6230 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
6231 -1, -1);
6232 }
6233
6234 private static void copyZipEntry(ZipEntry zipEntry,
6235 ZipFile inZipFile,
6236 ZipOutputStream outZipStream) throws IOException {
6237 byte[] buffer = new byte[4096];
6238 int num;
6239
6240 ZipEntry newEntry;
6241 if (zipEntry.getMethod() == ZipEntry.STORED) {
6242 // Preserve the STORED method of the input entry.
6243 newEntry = new ZipEntry(zipEntry);
6244 } else {
6245 // Create a new entry so that the compressed len is recomputed.
6246 newEntry = new ZipEntry(zipEntry.getName());
6247 }
6248 outZipStream.putNextEntry(newEntry);
6249
6250 InputStream data = inZipFile.getInputStream(zipEntry);
6251 while ((num = data.read(buffer)) > 0) {
6252 outZipStream.write(buffer, 0, num);
6253 }
6254 outZipStream.flush();
6255 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 private void deleteTempPackageFiles() {
6258 FilenameFilter filter = new FilenameFilter() {
6259 public boolean accept(File dir, String name) {
6260 return name.startsWith("vmdl") && name.endsWith(".tmp");
6261 }
6262 };
6263 String tmpFilesList[] = mAppInstallDir.list(filter);
6264 if(tmpFilesList == null) {
6265 return;
6266 }
6267 for(int i = 0; i < tmpFilesList.length; i++) {
6268 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
6269 tmpFile.delete();
6270 }
6271 }
6272
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006273 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 File tmpPackageFile;
6275 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006276 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006278 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 return null;
6280 }
6281 try {
6282 FileUtils.setPermissions(
6283 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
6284 -1, -1);
6285 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006286 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 return null;
6288 }
6289 return tmpPackageFile;
6290 }
6291
6292 public void deletePackage(final String packageName,
6293 final IPackageDeleteObserver observer,
6294 final int flags) {
6295 mContext.enforceCallingOrSelfPermission(
6296 android.Manifest.permission.DELETE_PACKAGES, null);
6297 // Queue up an async operation since the package deletion may take a little while.
6298 mHandler.post(new Runnable() {
6299 public void run() {
6300 mHandler.removeCallbacks(this);
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006301 final int returnCode = deletePackageX(packageName, true, true, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 if (observer != null) {
6303 try {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006304 observer.packageDeleted(packageName, returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006305 } catch (RemoteException e) {
6306 Log.i(TAG, "Observer no longer exists.");
6307 } //end catch
6308 } //end if
6309 } //end run
6310 });
6311 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 /**
6314 * This method is an internal method that could be get invoked either
6315 * to delete an installed package or to clean up a failed installation.
6316 * After deleting an installed package, a broadcast is sent to notify any
6317 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006318 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 * installation wouldn't have sent the initial broadcast either
6320 * The key steps in deleting a package are
6321 * deleting the package information in internal structures like mPackages,
6322 * deleting the packages base directories through installd
6323 * updating mSettings to reflect current status
6324 * persisting settings for later use
6325 * sending a broadcast if necessary
6326 */
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006327 private int deletePackageX(String packageName, boolean sendBroadCast,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 boolean deleteCodeAndResources, int flags) {
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006329 final PackageRemovedInfo info = new PackageRemovedInfo();
6330 final boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006332 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
6333 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
6334 try {
6335 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006336 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006337 return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006338 }
6339 } catch (RemoteException e) {
6340 }
6341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006343 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006344 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006346
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006347 if (res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07006348 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006349 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07006350
6351 // If the removed package was a system update, the old system packaged
6352 // was re-enabled; we need to broadcast this information
6353 if (systemUpdate) {
6354 Bundle extras = new Bundle(1);
6355 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
6356 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6357
Dianne Hackborne7f97212011-02-24 14:40:20 -08006358 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
6359 extras, null, null);
6360 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
6361 extras, null, null);
6362 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
6363 null, packageName, null);
Romain Guy96f43572009-03-24 20:27:49 -07006364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006366 // Force a gc here.
6367 Runtime.getRuntime().gc();
6368 // Delete the resources here after sending the broadcast to let
6369 // other processes clean up before deleting resources.
6370 if (info.args != null) {
6371 synchronized (mInstallLock) {
6372 info.args.doPostDeleteLI(deleteCodeAndResources);
6373 }
6374 }
Kenny Rootc39bb4a2011-02-28 13:27:19 -08006375
6376 return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 }
6378
6379 static class PackageRemovedInfo {
6380 String removedPackage;
6381 int uid = -1;
6382 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07006383 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006384 // Clean up resources deleted packages.
6385 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07006386
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006387 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006388 Bundle extras = new Bundle(1);
6389 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
6390 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
6391 if (replacing) {
6392 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6393 }
6394 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08006395 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
6396 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006397 }
6398 if (removedUid >= 0) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08006399 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006400 }
6401 }
6402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 /*
6405 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
6406 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006407 * 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 -08006408 * delete a partially installed application.
6409 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006410 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006411 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006413 if (outInfo != null) {
6414 outInfo.removedPackage = packageName;
6415 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006416 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006417 // Retrieve object to delete permissions for shared user later on
Kenny Root447106f2011-03-23 11:00:15 -07006418 final PackageSetting deletedPs;
6419 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 synchronized (mPackages) {
6421 deletedPs = mSettings.mPackages.get(packageName);
6422 }
6423 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6424 if (mInstaller != null) {
Amith Yamasani0b285492011-04-14 17:35:23 -07006425 int retCode = mInstaller.remove(packageName, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006427 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428 + packageName + ", retcode=" + retCode);
6429 // we don't consider this to be a failure of the core package deletion
Amith Yamasani0b285492011-04-14 17:35:23 -07006430 } else {
6431 // TODO: Kill the processes first
6432 mUserManager.removePackageForAllUsers(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 }
6434 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006435 // for simulator
Kenny Root447106f2011-03-23 11:00:15 -07006436 File dataDir;
6437 // reader
6438 synchronized (mPackages) {
6439 PackageParser.Package pkg = mPackages.get(packageName);
6440 dataDir = new File(pkg.applicationInfo.dataDir);
6441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 dataDir.delete();
6443 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07006444 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 }
Kenny Root447106f2011-03-23 11:00:15 -07006446 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006448 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006449 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6450 if (outInfo != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006451 outInfo.removedUid = mSettings.removePackageLPw(packageName);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006452 }
6453 if (deletedPs != null) {
Kenny Root447106f2011-03-23 11:00:15 -07006454 updatePermissionsLPw(deletedPs.name, null, false, false, false);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006455 if (deletedPs.sharedUser != null) {
6456 // remove permissions associated with package
Kenny Root447106f2011-03-23 11:00:15 -07006457 mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006458 }
6459 }
6460 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006461 // remove from preferred activities.
6462 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
6463 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08006464 if (pa.mPref.mComponent.getPackageName().equals(deletedPs.name)) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006465 removed.add(pa);
6466 }
6467 }
6468 for (PreferredActivity pa : removed) {
6469 mSettings.mPreferredActivities.removeFilter(pa);
6470 }
6471 }
Kenny Root447106f2011-03-23 11:00:15 -07006472 // can downgrade to reader
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006473 if (writeSettings) {
6474 // Save settings now
Kenny Root447106f2011-03-23 11:00:15 -07006475 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006476 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 }
6478 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 /*
6481 * Tries to delete system package.
6482 */
6483 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006484 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 ApplicationInfo applicationInfo = p.applicationInfo;
6486 //applicable for non-partially installed applications only
6487 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006488 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 return false;
6490 }
6491 PackageSetting ps = null;
6492 // Confirm if the system package has been updated
6493 // An updated system app can be deleted. This will also have to restore
6494 // the system pkg from system partition
Kenny Root447106f2011-03-23 11:00:15 -07006495 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006497 ps = mSettings.getDisabledSystemPkgLPr(p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 }
6499 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006500 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 return false;
6502 } else {
6503 Log.i(TAG, "Deleting system pkg from data partition");
6504 }
6505 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07006506 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006507 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006508 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006509 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006510 } else {
6511 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006512 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006513 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006514 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006515 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 if (!ret) {
6517 return false;
6518 }
Kenny Root447106f2011-03-23 11:00:15 -07006519 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 synchronized (mPackages) {
6521 // Reinstate the old system package
Kenny Root447106f2011-03-23 11:00:15 -07006522 mSettings.enableSystemPackageLPw(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07006523 // Remove any native libraries from the upgraded package.
6524 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 }
6526 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006527 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006529 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006532 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 return false;
6534 }
Kenny Root447106f2011-03-23 11:00:15 -07006535 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006537 updatePermissionsLPw(newPkg.packageName, newPkg, true, true, false);
6538 // can downgrade to reader here
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006539 if (writeSettings) {
Kenny Root447106f2011-03-23 11:00:15 -07006540 mSettings.writeLPr();
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 }
6543 return true;
6544 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006547 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6548 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006549 ApplicationInfo applicationInfo = p.applicationInfo;
6550 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006551 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 return false;
6553 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006554 if (outInfo != null) {
6555 outInfo.uid = applicationInfo.uid;
6556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006557
6558 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006559 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560
6561 // Delete application code and resources
6562 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006563 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07006564 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
6565 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
6566 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
6567 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 }
6569 return true;
6570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006572 /*
6573 * This method handles package deletion in general
6574 */
6575 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006576 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6577 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006578 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006579 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 return false;
6581 }
6582 PackageParser.Package p;
6583 boolean dataOnly = false;
6584 synchronized (mPackages) {
6585 p = mPackages.get(packageName);
6586 if (p == null) {
6587 //this retrieves partially installed apps
6588 dataOnly = true;
6589 PackageSetting ps = mSettings.mPackages.get(packageName);
6590 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006591 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 return false;
6593 }
6594 p = ps.pkg;
6595 }
6596 }
6597 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006598 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006599 return false;
6600 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 if (dataOnly) {
6603 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006604 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006605 return true;
6606 }
6607 // At this point the package should have ApplicationInfo associated with it
6608 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006609 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610 return false;
6611 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006612 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07006613 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006614 Log.i(TAG, "Removing system package:"+p.packageName);
6615 // When an updated system application is deleted we delete the existing resources as well and
6616 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006617 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006618 } else {
6619 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006620 // Kill application pre-emptively especially for apps on sd.
6621 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006622 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
6623 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006625 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006626 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 public void clearApplicationUserData(final String packageName,
6629 final IPackageDataObserver observer) {
6630 mContext.enforceCallingOrSelfPermission(
6631 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
6632 // Queue up an async operation since the package deletion may take a little while.
6633 mHandler.post(new Runnable() {
6634 public void run() {
6635 mHandler.removeCallbacks(this);
6636 final boolean succeeded;
6637 synchronized (mInstallLock) {
6638 succeeded = clearApplicationUserDataLI(packageName);
6639 }
6640 if (succeeded) {
6641 // invoke DeviceStorageMonitor's update method to clear any notifications
6642 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
6643 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
6644 if (dsm != null) {
6645 dsm.updateMemory();
6646 }
6647 }
6648 if(observer != null) {
6649 try {
6650 observer.onRemoveCompleted(packageName, succeeded);
6651 } catch (RemoteException e) {
6652 Log.i(TAG, "Observer no longer exists.");
6653 }
6654 } //end if observer
6655 } //end run
6656 });
6657 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 private boolean clearApplicationUserDataLI(String packageName) {
6660 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006661 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 return false;
6663 }
6664 PackageParser.Package p;
6665 boolean dataOnly = false;
6666 synchronized (mPackages) {
6667 p = mPackages.get(packageName);
6668 if(p == null) {
6669 dataOnly = true;
6670 PackageSetting ps = mSettings.mPackages.get(packageName);
6671 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006672 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 return false;
6674 }
6675 p = ps.pkg;
6676 }
6677 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006678
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08006679 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 //need to check this only for fully installed applications
6681 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006682 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 return false;
6684 }
6685 final ApplicationInfo applicationInfo = p.applicationInfo;
6686 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006687 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 return false;
6689 }
6690 }
6691 if (mInstaller != null) {
Amith Yamasani0b285492011-04-14 17:35:23 -07006692 int retCode = mInstaller.clearUserData(packageName, 0); // TODO - correct userId
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006694 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 + packageName);
6696 return false;
6697 }
6698 }
6699 return true;
6700 }
6701
6702 public void deleteApplicationCacheFiles(final String packageName,
6703 final IPackageDataObserver observer) {
6704 mContext.enforceCallingOrSelfPermission(
6705 android.Manifest.permission.DELETE_CACHE_FILES, null);
6706 // Queue up an async operation since the package deletion may take a little while.
6707 mHandler.post(new Runnable() {
6708 public void run() {
6709 mHandler.removeCallbacks(this);
6710 final boolean succeded;
6711 synchronized (mInstallLock) {
6712 succeded = deleteApplicationCacheFilesLI(packageName);
6713 }
6714 if(observer != null) {
6715 try {
6716 observer.onRemoveCompleted(packageName, succeded);
6717 } catch (RemoteException e) {
6718 Log.i(TAG, "Observer no longer exists.");
6719 }
6720 } //end if observer
6721 } //end run
6722 });
6723 }
6724
6725 private boolean deleteApplicationCacheFilesLI(String packageName) {
6726 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006727 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006728 return false;
6729 }
6730 PackageParser.Package p;
6731 synchronized (mPackages) {
6732 p = mPackages.get(packageName);
6733 }
6734 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006735 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 return false;
6737 }
6738 final ApplicationInfo applicationInfo = p.applicationInfo;
6739 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006740 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006741 return false;
6742 }
6743 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006744 int retCode = mInstaller.deleteCacheFiles(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006746 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006747 + packageName);
6748 return false;
6749 }
6750 }
6751 return true;
6752 }
6753
6754 public void getPackageSizeInfo(final String packageName,
6755 final IPackageStatsObserver observer) {
6756 mContext.enforceCallingOrSelfPermission(
6757 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6758 // Queue up an async operation since the package deletion may take a little while.
6759 mHandler.post(new Runnable() {
6760 public void run() {
6761 mHandler.removeCallbacks(this);
Kenny Root366949c2011-01-14 17:18:14 -08006762 PackageStats stats = new PackageStats(packageName);
6763
6764 final boolean success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 synchronized (mInstallLock) {
Kenny Root366949c2011-01-14 17:18:14 -08006766 success = getPackageSizeInfoLI(packageName, stats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 }
Kenny Root366949c2011-01-14 17:18:14 -08006768
6769 Message msg = mHandler.obtainMessage(INIT_COPY);
6770 msg.obj = new MeasureParams(stats, success, observer);
6771 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 } //end run
6773 });
6774 }
6775
6776 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6777 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006778 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 return false;
6780 }
6781 PackageParser.Package p;
6782 boolean dataOnly = false;
6783 synchronized (mPackages) {
6784 p = mPackages.get(packageName);
6785 if(p == null) {
6786 dataOnly = true;
6787 PackageSetting ps = mSettings.mPackages.get(packageName);
6788 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006789 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 return false;
6791 }
6792 p = ps.pkg;
6793 }
6794 }
6795 String publicSrcDir = null;
6796 if(!dataOnly) {
6797 final ApplicationInfo applicationInfo = p.applicationInfo;
6798 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006799 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006800 return false;
6801 }
6802 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6803 }
6804 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006805 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 if (res < 0) {
6807 return false;
6808 } else {
6809 return true;
6810 }
6811 }
6812 return true;
6813 }
6814
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006817 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 }
6819
6820 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006821 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006822 }
6823
6824 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006825 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006826 }
6827
Kenny Root447106f2011-03-23 11:00:15 -07006828 private int getUidTargetSdkVersionLockedLPr(int uid) {
6829 Object obj = mSettings.getUserIdLPr(uid);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006830 if (obj instanceof SharedUserSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07006831 final SharedUserSetting sus = (SharedUserSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006832 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
Kenny Root60f7ad82011-03-22 12:49:06 -07006833 final Iterator<PackageSetting> it = sus.packages.iterator();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006834 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07006835 final PackageSetting ps = it.next();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006836 if (ps.pkg != null) {
6837 int v = ps.pkg.applicationInfo.targetSdkVersion;
6838 if (v < vers) vers = v;
6839 }
6840 }
6841 return vers;
6842 } else if (obj instanceof PackageSetting) {
Kenny Root60f7ad82011-03-22 12:49:06 -07006843 final PackageSetting ps = (PackageSetting) obj;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006844 if (ps.pkg != null) {
6845 return ps.pkg.applicationInfo.targetSdkVersion;
6846 }
6847 }
6848 return Build.VERSION_CODES.CUR_DEVELOPMENT;
6849 }
6850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 public void addPreferredActivity(IntentFilter filter, int match,
6852 ComponentName[] set, ComponentName activity) {
Kenny Root447106f2011-03-23 11:00:15 -07006853 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006855 if (mContext.checkCallingOrSelfPermission(
6856 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6857 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07006858 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006859 < Build.VERSION_CODES.FROYO) {
6860 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
6861 + Binder.getCallingUid());
6862 return;
6863 }
6864 mContext.enforceCallingOrSelfPermission(
6865 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6866 }
6867
6868 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6870 mSettings.mPreferredActivities.addFilter(
6871 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006872 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006873 }
6874 }
6875
Satish Sampath8dbe6122009-06-02 23:35:54 +01006876 public void replacePreferredActivity(IntentFilter filter, int match,
6877 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01006878 if (filter.countActions() != 1) {
6879 throw new IllegalArgumentException(
6880 "replacePreferredActivity expects filter to have only 1 action.");
6881 }
6882 if (filter.countCategories() != 1) {
6883 throw new IllegalArgumentException(
6884 "replacePreferredActivity expects filter to have only 1 category.");
6885 }
6886 if (filter.countDataAuthorities() != 0
6887 || filter.countDataPaths() != 0
6888 || filter.countDataSchemes() != 0
6889 || filter.countDataTypes() != 0) {
6890 throw new IllegalArgumentException(
6891 "replacePreferredActivity expects filter to have no data authorities, " +
6892 "paths, schemes or types.");
6893 }
6894 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006895 if (mContext.checkCallingOrSelfPermission(
6896 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6897 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07006898 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006899 < Build.VERSION_CODES.FROYO) {
6900 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
6901 + Binder.getCallingUid());
6902 return;
6903 }
6904 mContext.enforceCallingOrSelfPermission(
6905 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6906 }
6907
Satish Sampath8dbe6122009-06-02 23:35:54 +01006908 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6909 String action = filter.getAction(0);
6910 String category = filter.getCategory(0);
6911 while (it.hasNext()) {
6912 PreferredActivity pa = it.next();
6913 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6914 it.remove();
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08006915 Log.i(TAG, "Removed preferred activity " + pa.mPref.mComponent + ":");
Satish Sampath8dbe6122009-06-02 23:35:54 +01006916 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6917 }
6918 }
6919 addPreferredActivity(filter, match, set, activity);
6920 }
6921 }
6922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 public void clearPackagePreferredActivities(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07006924 final int uid = Binder.getCallingUid();
6925 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006927 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006928 if (pkg == null || pkg.applicationInfo.uid != uid) {
6929 if (mContext.checkCallingOrSelfPermission(
6930 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6931 != PackageManager.PERMISSION_GRANTED) {
Kenny Root447106f2011-03-23 11:00:15 -07006932 if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006933 < Build.VERSION_CODES.FROYO) {
6934 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
6935 + Binder.getCallingUid());
6936 return;
6937 }
6938 mContext.enforceCallingOrSelfPermission(
6939 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6940 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006941 }
6942
Kenny Root447106f2011-03-23 11:00:15 -07006943 if (clearPackagePreferredActivitiesLPw(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006944 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 }
6946 }
6947 }
6948
Kenny Root447106f2011-03-23 11:00:15 -07006949 boolean clearPackagePreferredActivitiesLPw(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950 boolean changed = false;
6951 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6952 while (it.hasNext()) {
6953 PreferredActivity pa = it.next();
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08006954 if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 it.remove();
6956 changed = true;
6957 }
6958 }
6959 return changed;
6960 }
6961
6962 public int getPreferredActivities(List<IntentFilter> outFilters,
6963 List<ComponentName> outActivities, String packageName) {
6964
6965 int num = 0;
Kenny Root447106f2011-03-23 11:00:15 -07006966 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07006968 final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 while (it.hasNext()) {
Kenny Root447106f2011-03-23 11:00:15 -07006970 final PreferredActivity pa = it.next();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 if (packageName == null
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08006972 || pa.mPref.mComponent.getPackageName().equals(packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 if (outFilters != null) {
6974 outFilters.add(new IntentFilter(pa));
6975 }
6976 if (outActivities != null) {
Dianne Hackbornf8b8a3f2011-03-04 00:05:31 -08006977 outActivities.add(pa.mPref.mComponent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006978 }
6979 }
6980 }
6981 }
6982
6983 return num;
6984 }
6985
6986 public void setApplicationEnabledSetting(String appPackageName,
6987 int newState, int flags) {
6988 setEnabledSetting(appPackageName, null, newState, flags);
6989 }
6990
6991 public void setComponentEnabledSetting(ComponentName componentName,
6992 int newState, int flags) {
6993 setEnabledSetting(componentName.getPackageName(),
6994 componentName.getClassName(), newState, flags);
6995 }
6996
6997 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006998 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006999 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
7000 || newState == COMPONENT_ENABLED_STATE_ENABLED
7001 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
7002 throw new IllegalArgumentException("Invalid new component state: "
7003 + newState);
7004 }
7005 PackageSetting pkgSetting;
7006 final int uid = Binder.getCallingUid();
7007 final int permission = mContext.checkCallingPermission(
7008 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
7009 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007010 boolean sendNow = false;
7011 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007012 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007014 ArrayList<String> components;
Kenny Root447106f2011-03-23 11:00:15 -07007015
7016 // writer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007017 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007018 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007019 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007020 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007022 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007023 }
7024 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007025 "Unknown component: " + packageName
7026 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 }
7028 if (!allowedByPermission && (uid != pkgSetting.userId)) {
7029 throw new SecurityException(
7030 "Permission Denial: attempt to change component state from pid="
7031 + Binder.getCallingPid()
7032 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
7033 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007034 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007035 // We're dealing with an application/package level state change
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007036 if (pkgSetting.enabled == newState) {
7037 // Nothing to do
7038 return;
7039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007040 pkgSetting.enabled = newState;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07007041 pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007042 } else {
7043 // We're dealing with a component level state change
7044 switch (newState) {
7045 case COMPONENT_ENABLED_STATE_ENABLED:
Kenny Root447106f2011-03-23 11:00:15 -07007046 if (!pkgSetting.enableComponentLPw(className)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007047 return;
7048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 break;
7050 case COMPONENT_ENABLED_STATE_DISABLED:
Kenny Root447106f2011-03-23 11:00:15 -07007051 if (!pkgSetting.disableComponentLPw(className)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007052 return;
7053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 break;
7055 case COMPONENT_ENABLED_STATE_DEFAULT:
Kenny Root447106f2011-03-23 11:00:15 -07007056 if (!pkgSetting.restoreComponentLPw(className)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007057 return;
7058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 break;
7060 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007061 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007062 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 }
7064 }
Kenny Root447106f2011-03-23 11:00:15 -07007065 mSettings.writeLPr();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007066 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007067 components = mPendingBroadcasts.get(packageName);
Kenny Root447106f2011-03-23 11:00:15 -07007068 final boolean newPackage = components == null;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007069 if (newPackage) {
7070 components = new ArrayList<String>();
7071 }
7072 if (!components.contains(componentName)) {
7073 components.add(componentName);
7074 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007075 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
7076 sendNow = true;
7077 // Purge entry from pending broadcast list if another one exists already
7078 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007079 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007080 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007081 if (newPackage) {
7082 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007083 }
7084 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
7085 // Schedule a message
7086 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
7087 }
7088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007089 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 long callingId = Binder.clearCallingIdentity();
7092 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007093 if (sendNow) {
7094 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007095 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 } finally {
7098 Binder.restoreCallingIdentity(callingId);
7099 }
7100 }
7101
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007102 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007103 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
Kenny Root4dfe6ff2011-02-23 17:00:43 -08007104 if (DEBUG_INSTALL)
7105 Log.v(TAG, "Sending package changed: package=" + packageName + " components="
7106 + componentNames);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08007107 Bundle extras = new Bundle(4);
7108 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
7109 String nameList[] = new String[componentNames.size()];
7110 componentNames.toArray(nameList);
7111 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007112 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
7113 extras.putInt(Intent.EXTRA_UID, packageUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007114 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null);
7115 }
7116
7117 public void setPackageStoppedState(String packageName, boolean stopped) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08007118 final int uid = Binder.getCallingUid();
7119 final int permission = mContext.checkCallingOrSelfPermission(
7120 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
7121 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Kenny Root447106f2011-03-23 11:00:15 -07007122 // writer
Dianne Hackborne7f97212011-02-24 14:40:20 -08007123 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007124 if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission,
7125 uid)) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08007126 scheduleWriteStoppedPackagesLocked();
7127 }
7128 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007129 }
7130
Jacek Surazski65e13172009-04-28 15:26:38 +02007131 public String getInstallerPackageName(String packageName) {
Kenny Root447106f2011-03-23 11:00:15 -07007132 // reader
Jacek Surazski65e13172009-04-28 15:26:38 +02007133 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007134 return mSettings.getInstallerPackageNameLPr(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02007135 }
7136 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007137
Kenny Root447106f2011-03-23 11:00:15 -07007138 public int getApplicationEnabledSetting(String packageName) {
7139 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007141 return mSettings.getApplicationEnabledSettingLPr(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 }
7143 }
7144
7145 public int getComponentEnabledSetting(ComponentName componentName) {
Kenny Root447106f2011-03-23 11:00:15 -07007146 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007148 return mSettings.getComponentEnabledSettingLPr(componentName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 }
7150 }
7151
7152 public void enterSafeMode() {
7153 if (!mSystemReady) {
7154 mSafeMode = true;
7155 }
7156 }
7157
7158 public void systemReady() {
7159 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007160
7161 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007162 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007163 mContext.getContentResolver(),
7164 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007165 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007166 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007167 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007169 }
7170
7171 public boolean isSafeMode() {
7172 return mSafeMode;
7173 }
7174
7175 public boolean hasSystemUidErrors() {
7176 return mHasSystemUidErrors;
7177 }
7178
7179 static String arrayToString(int[] array) {
7180 StringBuffer buf = new StringBuffer(128);
7181 buf.append('[');
7182 if (array != null) {
7183 for (int i=0; i<array.length; i++) {
7184 if (i > 0) buf.append(", ");
7185 buf.append(array[i]);
7186 }
7187 }
7188 buf.append(']');
7189 return buf.toString();
7190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007191
Kenny Root447106f2011-03-23 11:00:15 -07007192 static class DumpState {
7193 public static final int DUMP_LIBS = 1 << 0;
7194
7195 public static final int DUMP_FEATURES = 1 << 1;
7196
7197 public static final int DUMP_RESOLVERS = 1 << 2;
7198
7199 public static final int DUMP_PERMISSIONS = 1 << 3;
7200
7201 public static final int DUMP_PACKAGES = 1 << 4;
7202
7203 public static final int DUMP_SHARED_USERS = 1 << 5;
7204
7205 public static final int DUMP_MESSAGES = 1 << 6;
7206
7207 public static final int DUMP_PROVIDERS = 1 << 7;
7208
7209 public static final int OPTION_SHOW_FILTERS = 1 << 0;
7210
7211 private int mTypes;
7212
7213 private int mOptions;
7214
7215 private boolean mTitlePrinted;
7216
7217 private SharedUserSetting mSharedUser;
7218
7219 public boolean isDumping(int type) {
7220 if (mTypes == 0) {
7221 return true;
7222 }
7223
7224 return (mTypes & type) != 0;
7225 }
7226
7227 public void setDump(int type) {
7228 mTypes |= type;
7229 }
7230
7231 public boolean isOptionEnabled(int option) {
7232 return (mOptions & option) != 0;
7233 }
7234
7235 public void setOptionEnabled(int option) {
7236 mOptions |= option;
7237 }
7238
7239 public boolean onTitlePrinted() {
7240 final boolean printed = mTitlePrinted;
7241 mTitlePrinted = true;
7242 return printed;
7243 }
7244
7245 public boolean getTitlePrinted() {
7246 return mTitlePrinted;
7247 }
7248
7249 public void setTitlePrinted(boolean enabled) {
7250 mTitlePrinted = enabled;
7251 }
7252
7253 public SharedUserSetting getSharedUser() {
7254 return mSharedUser;
7255 }
7256
7257 public void setSharedUser(SharedUserSetting user) {
7258 mSharedUser = user;
7259 }
7260 }
7261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 @Override
7263 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7264 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
7265 != PackageManager.PERMISSION_GRANTED) {
7266 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7267 + Binder.getCallingPid()
7268 + ", uid=" + Binder.getCallingUid()
7269 + " without permission "
7270 + android.Manifest.permission.DUMP);
7271 return;
7272 }
7273
Kenny Root447106f2011-03-23 11:00:15 -07007274 DumpState dumpState = new DumpState();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007275
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007276 String packageName = null;
7277
7278 int opti = 0;
7279 while (opti < args.length) {
7280 String opt = args[opti];
7281 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7282 break;
7283 }
7284 opti++;
7285 if ("-a".equals(opt)) {
7286 // Right now we only know how to print all.
7287 } else if ("-h".equals(opt)) {
7288 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007289 pw.println(" [-h] [-f] [cmd] ...");
7290 pw.println(" -f: print details of intent filters");
7291 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007292 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007293 pw.println(" l[ibraries]: list known shared libraries");
7294 pw.println(" f[ibraries]: list device features");
7295 pw.println(" r[esolvers]: dump intent resolvers");
7296 pw.println(" perm[issions]: dump permissions");
7297 pw.println(" prov[iders]: dump content providers");
7298 pw.println(" p[ackages]: dump installed packages");
7299 pw.println(" s[hared-users]: dump shared user IDs");
7300 pw.println(" m[essages]: print collected runtime messages");
7301 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007302 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007303 } else if ("-f".equals(opt)) {
Kenny Root447106f2011-03-23 11:00:15 -07007304 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007305 } else {
7306 pw.println("Unknown argument: " + opt + "; use -h for help");
7307 }
7308 }
7309
7310 // Is the caller requesting to dump a particular piece of data?
7311 if (opti < args.length) {
7312 String cmd = args[opti];
7313 opti++;
7314 // Is this a package name?
7315 if ("android".equals(cmd) || cmd.contains(".")) {
7316 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007317 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007318 dumpState.setDump(DumpState.DUMP_LIBS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007319 } else if ("f".equals(cmd) || "features".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007320 dumpState.setDump(DumpState.DUMP_FEATURES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007321 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007322 dumpState.setDump(DumpState.DUMP_RESOLVERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007323 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007324 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007325 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007326 dumpState.setDump(DumpState.DUMP_PACKAGES);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007327 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007328 dumpState.setDump(DumpState.DUMP_SHARED_USERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007329 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007330 dumpState.setDump(DumpState.DUMP_PROVIDERS);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007331 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
Kenny Root447106f2011-03-23 11:00:15 -07007332 dumpState.setDump(DumpState.DUMP_MESSAGES);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007333 }
7334 }
Kenny Root447106f2011-03-23 11:00:15 -07007335
7336 // reader
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337 synchronized (mPackages) {
Kenny Root447106f2011-03-23 11:00:15 -07007338 if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
7339 if (dumpState.onTitlePrinted())
7340 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007341 pw.println("Libraries:");
Kenny Root447106f2011-03-23 11:00:15 -07007342 final Iterator<String> it = mSharedLibraries.keySet().iterator();
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007343 while (it.hasNext()) {
7344 String name = it.next();
7345 pw.print(" ");
7346 pw.print(name);
7347 pw.print(" -> ");
7348 pw.println(mSharedLibraries.get(name));
7349 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007350 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007351
Kenny Root447106f2011-03-23 11:00:15 -07007352 if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) {
7353 if (dumpState.onTitlePrinted())
7354 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007355 pw.println("Features:");
7356 Iterator<String> it = mAvailableFeatures.keySet().iterator();
7357 while (it.hasNext()) {
7358 String name = it.next();
7359 pw.print(" ");
7360 pw.println(name);
7361 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007362 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007363
Kenny Root447106f2011-03-23 11:00:15 -07007364 if (dumpState.isDumping(DumpState.DUMP_RESOLVERS)) {
7365 if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
7366 : "Activity Resolver Table:", " ", packageName,
7367 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
7368 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007369 }
Kenny Root447106f2011-03-23 11:00:15 -07007370 if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
7371 : "Receiver Resolver Table:", " ", packageName,
7372 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
7373 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007374 }
Kenny Root447106f2011-03-23 11:00:15 -07007375 if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
7376 : "Service Resolver Table:", " ", packageName,
7377 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
7378 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007379 }
Kenny Root447106f2011-03-23 11:00:15 -07007380 if (mSettings.mPreferredActivities.dump(pw,
7381 dumpState.getTitlePrinted() ? "\nPreferred Activities:"
7382 : "Preferred Activities:", " ",
7383 packageName, dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
7384 dumpState.setTitlePrinted(true);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007385 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007386 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007387
Kenny Root447106f2011-03-23 11:00:15 -07007388 if (dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
7389 mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007391
Kenny Root447106f2011-03-23 11:00:15 -07007392 if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
7393 boolean printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007394 for (PackageParser.Provider p : mProviders.values()) {
7395 if (packageName != null && !packageName.equals(p.info.packageName)) {
7396 continue;
7397 }
7398 if (!printedSomething) {
Kenny Root447106f2011-03-23 11:00:15 -07007399 if (dumpState.onTitlePrinted())
7400 pw.println(" ");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007401 pw.println("Registered ContentProviders:");
7402 printedSomething = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007403 }
7404 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
7405 pw.println(p.toString());
7406 }
7407 }
7408
Kenny Root447106f2011-03-23 11:00:15 -07007409 if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
7410 mSettings.dumpPackagesLPr(pw, packageName, dumpState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 }
Kenny Root447106f2011-03-23 11:00:15 -07007412
7413 if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
7414 mSettings.dumpSharedUsersLPr(pw, packageName, dumpState);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007415 }
Kenny Root447106f2011-03-23 11:00:15 -07007416
7417 if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
7418 if (dumpState.onTitlePrinted())
7419 pw.println(" ");
7420 mSettings.dumpReadMessagesLPr(pw, dumpState);
7421
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007422 pw.println(" ");
7423 pw.println("Package warning messages:");
Kenny Root447106f2011-03-23 11:00:15 -07007424 final File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007425 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007426 try {
7427 in = new FileInputStream(fname);
Kenny Root447106f2011-03-23 11:00:15 -07007428 final int avail = in.available();
7429 final byte[] data = new byte[avail];
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007430 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007431 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007432 } catch (FileNotFoundException e) {
7433 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007434 } finally {
7435 if (in != null) {
7436 try {
7437 in.close();
Kenny Root447106f2011-03-23 11:00:15 -07007438 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007439 }
7440 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007441 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007443 }
7444 }
7445
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007446 // ------- apps on sdcard specific code -------
7447 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root447106f2011-03-23 11:00:15 -07007448
Kenny Root305bcbf2010-09-03 07:56:38 -07007449 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
Kenny Root447106f2011-03-23 11:00:15 -07007450
Kenny Root305bcbf2010-09-03 07:56:38 -07007451 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
Kenny Root447106f2011-03-23 11:00:15 -07007452
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007453 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007454
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007455 private String getEncryptKey() {
7456 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07007457 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
7458 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007459 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07007460 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
7461 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007462 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007463 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007464 return null;
7465 }
7466 }
7467 return sdEncKey;
7468 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007469 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007470 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07007471 } catch (IOException ioe) {
Kenny Root447106f2011-03-23 11:00:15 -07007472 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " + ioe);
Rich Cannings8d578832010-09-09 15:12:40 -07007473 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007474 }
Rich Cannings8d578832010-09-09 15:12:40 -07007475
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007476 }
7477
Kenny Root447106f2011-03-23 11:00:15 -07007478 /* package */static String getTempContainerId() {
Kenny Rootc78a8072010-07-27 15:18:38 -07007479 int tmpIdx = 1;
7480 String list[] = PackageHelper.getSecureContainerList();
7481 if (list != null) {
7482 for (final String name : list) {
7483 // Ignore null and non-temporary container entries
7484 if (name == null || !name.startsWith(mTempContainerPrefix)) {
7485 continue;
7486 }
7487
7488 String subStr = name.substring(mTempContainerPrefix.length());
7489 try {
7490 int cid = Integer.parseInt(subStr);
7491 if (cid >= tmpIdx) {
7492 tmpIdx = cid + 1;
7493 }
7494 } catch (NumberFormatException e) {
7495 }
7496 }
7497 }
7498 return mTempContainerPrefix + tmpIdx;
7499 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007500
Kenny Root447106f2011-03-23 11:00:15 -07007501 /*
7502 * Update media status on PackageManager.
7503 */
7504 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
7505 int callingUid = Binder.getCallingUid();
7506 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
7507 throw new SecurityException("Media status can only be updated by the system");
7508 }
7509 // reader; this apparently protects mMediaMounted, but should probably
7510 // be a different lock in that case.
7511 synchronized (mPackages) {
7512 Log.i(TAG, "Updating external media status from "
7513 + (mMediaMounted ? "mounted" : "unmounted") + " to "
7514 + (mediaStatus ? "mounted" : "unmounted"));
7515 if (DEBUG_SD_INSTALL)
7516 Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + mediaStatus
7517 + ", mMediaMounted=" + mMediaMounted);
7518 if (mediaStatus == mMediaMounted) {
7519 final Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1
7520 : 0, -1);
7521 mHandler.sendMessage(msg);
7522 return;
7523 }
7524 mMediaMounted = mediaStatus;
7525 }
7526 // Queue up an async operation since the package installation may take a
7527 // little while.
7528 mHandler.post(new Runnable() {
7529 public void run() {
7530 // TODO fix this; this does nothing.
7531 mHandler.removeCallbacks(this);
7532 updateExternalMediaStatusInner(mediaStatus, reportStatus);
7533 }
7534 });
7535 }
7536
7537 /*
7538 * Collect information of applications on external media, map them against
7539 * existing containers and update information based on current mount status.
7540 * Please note that we always have to report status if reportStatus has been
7541 * set to true especially when unloading packages.
7542 */
7543 private void updateExternalMediaStatusInner(boolean mediaStatus, boolean reportStatus) {
7544 // Collection of uids
7545 int uidArr[] = null;
7546 // Collection of stale containers
7547 HashSet<String> removeCids = new HashSet<String>();
7548 // Collection of packages on external media with valid containers.
7549 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
7550 // Get list of secure containers.
7551 final String list[] = PackageHelper.getSecureContainerList();
7552 if (list == null || list.length == 0) {
7553 Log.i(TAG, "No secure containers on sdcard");
7554 } else {
7555 // Process list of secure containers and categorize them
7556 // as active or stale based on their package internal state.
7557 int uidList[] = new int[list.length];
7558 int num = 0;
7559 // reader
7560 synchronized (mPackages) {
7561 for (String cid : list) {
7562 SdInstallArgs args = new SdInstallArgs(cid);
7563 if (DEBUG_SD_INSTALL)
7564 Log.i(TAG, "Processing container " + cid);
7565 String pkgName = args.getPackageName();
7566 if (pkgName == null) {
7567 if (DEBUG_SD_INSTALL)
7568 Log.i(TAG, "Container : " + cid + " stale");
7569 removeCids.add(cid);
7570 continue;
7571 }
7572 if (DEBUG_SD_INSTALL)
7573 Log.i(TAG, "Looking for pkg : " + pkgName);
7574 PackageSetting ps = mSettings.mPackages.get(pkgName);
7575 // The package status is changed only if the code path
7576 // matches between settings and the container id.
7577 if (ps != null && ps.codePathString != null
7578 && ps.codePathString.equals(args.getCodePath())) {
7579 if (DEBUG_SD_INSTALL)
7580 Log.i(TAG, "Container : " + cid + " corresponds to pkg : " + pkgName
7581 + " at code path: " + ps.codePathString);
7582 // We do have a valid package installed on sdcard
7583 processCids.put(args, ps.codePathString);
7584 int uid = ps.userId;
7585 if (uid != -1) {
7586 uidList[num++] = uid;
7587 }
7588 } else {
7589 // Stale container on sdcard. Just delete
7590 if (DEBUG_SD_INSTALL)
7591 Log.i(TAG, "Container : " + cid + " stale");
7592 removeCids.add(cid);
7593 }
7594 }
7595 }
7596
7597 if (num > 0) {
7598 // Sort uid list
7599 Arrays.sort(uidList, 0, num);
7600 // Throw away duplicates
7601 uidArr = new int[num];
7602 uidArr[0] = uidList[0];
7603 int di = 0;
7604 for (int i = 1; i < num; i++) {
7605 if (uidList[i - 1] != uidList[i]) {
7606 uidArr[di++] = uidList[i];
7607 }
7608 }
7609 }
7610 }
7611 // Process packages with valid entries.
7612 if (mediaStatus) {
7613 if (DEBUG_SD_INSTALL)
7614 Log.i(TAG, "Loading packages");
7615 loadMediaPackages(processCids, uidArr, removeCids);
7616 startCleaningPackages();
7617 } else {
7618 if (DEBUG_SD_INSTALL)
7619 Log.i(TAG, "Unloading packages");
7620 unloadMediaPackages(processCids, uidArr, reportStatus);
7621 }
7622 }
7623
7624 private void sendResourcesChangedBroadcast(boolean mediaStatus, ArrayList<String> pkgList,
7625 int uidArr[], IIntentReceiver finishedReceiver) {
7626 int size = pkgList.size();
7627 if (size > 0) {
7628 // Send broadcasts here
7629 Bundle extras = new Bundle();
7630 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
7631 .toArray(new String[size]));
7632 if (uidArr != null) {
7633 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
7634 }
7635 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
7636 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
7637 sendPackageBroadcast(action, null, extras, null, finishedReceiver);
7638 }
7639 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007640
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07007641 /*
Kenny Root447106f2011-03-23 11:00:15 -07007642 * Look at potentially valid container ids from processCids If package
7643 * information doesn't match the one on record or package scanning fails,
7644 * the cid is added to list of removeCids. We currently don't delete stale
7645 * containers.
7646 */
7647 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[],
7648 HashSet<String> removeCids) {
7649 ArrayList<String> pkgList = new ArrayList<String>();
7650 Set<SdInstallArgs> keys = processCids.keySet();
7651 boolean doGc = false;
7652 for (SdInstallArgs args : keys) {
7653 String codePath = processCids.get(args);
7654 if (DEBUG_SD_INSTALL)
7655 Log.i(TAG, "Loading container : " + args.cid);
7656 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
7657 try {
7658 // Make sure there are no container errors first.
7659 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
7660 Slog.e(TAG, "Failed to mount cid : " + args.cid
7661 + " when installing from sdcard");
7662 continue;
7663 }
7664 // Check code path here.
7665 if (codePath == null || !codePath.equals(args.getCodePath())) {
7666 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()
7667 + " does not match one in settings " + codePath);
7668 continue;
7669 }
7670 // Parse package
7671 int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
7672 doGc = true;
7673 synchronized (mInstallLock) {
7674 final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
7675 0, 0);
7676 // Scan the package
7677 if (pkg != null) {
7678 /*
7679 * TODO why is the lock being held? doPostInstall is
7680 * called in other places without the lock. This needs
7681 * to be straightened out.
7682 */
7683 // writer
7684 synchronized (mPackages) {
7685 retCode = PackageManager.INSTALL_SUCCEEDED;
7686 pkgList.add(pkg.packageName);
7687 // Post process args
7688 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
7689 }
7690 } else {
7691 Slog.i(TAG, "Failed to install pkg from " + codePath + " from sdcard");
7692 }
7693 }
7694
7695 } finally {
7696 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
7697 // Don't destroy container here. Wait till gc clears things
7698 // up.
7699 removeCids.add(args.cid);
7700 }
7701 }
7702 }
7703 // writer
7704 synchronized (mPackages) {
7705 // If the platform SDK has changed since the last time we booted,
7706 // we need to re-grant app permission to catch any new ones that
7707 // appear. This is really a hack, and means that apps can in some
7708 // cases get permissions that the user didn't initially explicitly
7709 // allow... it would be nice to have some better way to handle
7710 // this situation.
7711 final boolean regrantPermissions = mSettings.mExternalSdkPlatform != mSdkVersion;
7712 if (regrantPermissions)
7713 Slog.i(TAG, "Platform changed from " + mSettings.mExternalSdkPlatform + " to "
7714 + mSdkVersion + "; regranting permissions for external storage");
7715 mSettings.mExternalSdkPlatform = mSdkVersion;
7716
7717 // Make sure group IDs have been assigned, and any permission
7718 // changes in other apps are accounted for
7719 updatePermissionsLPw(null, null, true, regrantPermissions, regrantPermissions);
7720 // can downgrade to reader
7721 // Persist settings
7722 mSettings.writeLPr();
7723 }
7724 // Send a broadcast to let everyone know we are done processing
7725 if (pkgList.size() > 0) {
7726 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
7727 }
7728 // Force gc to avoid any stale parser references that we might have.
7729 if (doGc) {
7730 Runtime.getRuntime().gc();
7731 }
7732 // List stale containers and destroy stale temporary containers.
7733 if (removeCids != null) {
7734 for (String cid : removeCids) {
7735 if (cid.startsWith(mTempContainerPrefix)) {
7736 Log.i(TAG, "Destroying stale temporary container " + cid);
7737 PackageHelper.destroySdDir(cid);
7738 } else {
7739 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007740 }
7741 }
Kenny Root447106f2011-03-23 11:00:15 -07007742 }
7743 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007744
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007745 /*
Kenny Root447106f2011-03-23 11:00:15 -07007746 * Utility method to unload a list of specified containers
7747 */
7748 private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
7749 // Just unmount all valid containers.
7750 for (SdInstallArgs arg : cidArgs) {
7751 synchronized (mInstallLock) {
7752 arg.doPostDeleteLI(false);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08007753 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08007754 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007755 }
7756
Kenny Root447106f2011-03-23 11:00:15 -07007757 /*
7758 * Unload packages mounted on external media. This involves deleting package
7759 * data from internal structures, sending broadcasts about diabled packages,
7760 * gc'ing to free up references, unmounting all secure containers
7761 * corresponding to packages on external media, and posting a
7762 * UPDATED_MEDIA_STATUS message if status has been requested. Please note
7763 * that we always have to post this message if status has been requested no
7764 * matter what.
7765 */
7766 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[],
7767 final boolean reportStatus) {
7768 if (DEBUG_SD_INSTALL)
7769 Log.i(TAG, "unloading media packages");
7770 ArrayList<String> pkgList = new ArrayList<String>();
7771 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
7772 final Set<SdInstallArgs> keys = processCids.keySet();
7773 for (SdInstallArgs args : keys) {
7774 String pkgName = args.getPackageName();
7775 if (DEBUG_SD_INSTALL)
7776 Log.i(TAG, "Trying to unload pkg : " + pkgName);
7777 // Delete package internally
7778 PackageRemovedInfo outInfo = new PackageRemovedInfo();
7779 synchronized (mInstallLock) {
7780 boolean res = deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
7781 outInfo, false);
7782 if (res) {
7783 pkgList.add(pkgName);
7784 } else {
7785 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
7786 failedList.add(args);
7787 }
7788 }
7789 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07007790
Kenny Root447106f2011-03-23 11:00:15 -07007791 // reader
7792 synchronized (mPackages) {
7793 // We didn't update the settings after removing each package;
7794 // write them now for all packages.
7795 mSettings.writeLPr();
7796 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007797
Kenny Root447106f2011-03-23 11:00:15 -07007798 // We have to absolutely send UPDATED_MEDIA_STATUS only
7799 // after confirming that all the receivers processed the ordered
7800 // broadcast when packages get disabled, force a gc to clean things up.
7801 // and unload all the containers.
7802 if (pkgList.size() > 0) {
7803 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
7804 public void performReceive(Intent intent, int resultCode, String data,
7805 Bundle extras, boolean ordered, boolean sticky) throws RemoteException {
7806 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
7807 reportStatus ? 1 : 0, 1, keys);
7808 mHandler.sendMessage(msg);
7809 }
7810 });
7811 } else {
7812 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, -1,
7813 keys);
7814 mHandler.sendMessage(msg);
7815 }
7816 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07007817
Kenny Root447106f2011-03-23 11:00:15 -07007818 public void movePackage(final String packageName, final IPackageMoveObserver observer,
7819 final int flags) {
7820 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
7821 int returnCode = PackageManager.MOVE_SUCCEEDED;
7822 int currFlags = 0;
7823 int newFlags = 0;
7824 // reader
7825 synchronized (mPackages) {
7826 PackageParser.Package pkg = mPackages.get(packageName);
7827 if (pkg == null) {
7828 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
7829 } else {
7830 // Disable moving fwd locked apps and system packages
7831 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
7832 Slog.w(TAG, "Cannot move system application");
7833 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
7834 } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
7835 Slog.w(TAG, "Cannot move forward locked app.");
7836 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
7837 } else if (pkg.mOperationPending) {
7838 Slog.w(TAG, "Attempt to move package which has pending operations");
7839 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
7840 } else {
7841 // Find install location first
7842 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0
7843 && (flags & PackageManager.MOVE_INTERNAL) != 0) {
7844 Slog.w(TAG, "Ambigous flags specified for move location.");
7845 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
7846 } else {
7847 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? PackageManager.INSTALL_EXTERNAL
7848 : PackageManager.INSTALL_INTERNAL;
7849 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
7850 : PackageManager.INSTALL_INTERNAL;
7851 if (newFlags == currFlags) {
7852 Slog.w(TAG, "No move required. Trying to move to same location");
7853 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
7854 }
7855 }
7856 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
7857 pkg.mOperationPending = true;
7858 }
7859 }
7860 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007861
Kenny Root447106f2011-03-23 11:00:15 -07007862 /*
7863 * TODO this next block probably shouldn't be inside the lock. We
7864 * can't guarantee these won't change after this is fired off
7865 * anyway.
7866 */
7867 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root85387d72010-08-26 10:13:11 -07007868 processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
Kenny Root447106f2011-03-23 11:00:15 -07007869 } else {
7870 Message msg = mHandler.obtainMessage(INIT_COPY);
7871 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -07007872 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
Kenny Root447106f2011-03-23 11:00:15 -07007873 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
Kenny Root85387d72010-08-26 10:13:11 -07007874 pkg.applicationInfo.dataDir);
Kenny Root447106f2011-03-23 11:00:15 -07007875 msg.obj = mp;
7876 mHandler.sendMessage(msg);
7877 }
7878 }
7879 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007880
Kenny Root447106f2011-03-23 11:00:15 -07007881 private void processPendingMove(final MoveParams mp, final int currentStatus) {
7882 // Queue up an async operation since the package deletion may take a
7883 // little while.
7884 mHandler.post(new Runnable() {
7885 public void run() {
7886 // TODO fix this; this does nothing.
7887 mHandler.removeCallbacks(this);
7888 int returnCode = currentStatus;
7889 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
7890 int uidArr[] = null;
7891 ArrayList<String> pkgList = null;
7892 synchronized (mPackages) {
7893 PackageParser.Package pkg = mPackages.get(mp.packageName);
7894 if (pkg == null) {
7895 Slog.w(TAG, " Package " + mp.packageName
7896 + " doesn't exist. Aborting move");
7897 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
7898 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
7899 Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
7900 + mp.srcArgs.getCodePath() + " to "
7901 + pkg.applicationInfo.sourceDir
7902 + " Aborting move and returning error");
7903 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
7904 } else {
7905 uidArr = new int[] {
7906 pkg.applicationInfo.uid
7907 };
7908 pkgList = new ArrayList<String>();
7909 pkgList.add(mp.packageName);
7910 }
7911 }
7912 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
7913 // Send resources unavailable broadcast
7914 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
7915 // Update package code and resource paths
7916 synchronized (mInstallLock) {
7917 synchronized (mPackages) {
7918 PackageParser.Package pkg = mPackages.get(mp.packageName);
7919 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -07007920 if (pkg == null) {
7921 Slog.w(TAG, " Package " + mp.packageName
7922 + " doesn't exist. Aborting move");
7923 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Kenny Root447106f2011-03-23 11:00:15 -07007924 } else if (!mp.srcArgs.getCodePath().equals(
7925 pkg.applicationInfo.sourceDir)) {
7926 Slog.w(TAG, "Package " + mp.packageName
7927 + " code path changed from " + mp.srcArgs.getCodePath()
7928 + " to " + pkg.applicationInfo.sourceDir
7929 + " Aborting move and returning error");
7930 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
7931 } else {
7932 final String oldCodePath = pkg.mPath;
7933 final String newCodePath = mp.targetArgs.getCodePath();
7934 final String newResPath = mp.targetArgs.getResourcePath();
7935 final String newNativePath = mp.targetArgs
7936 .getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -07007937
7938 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) {
7939 if (mInstaller
7940 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
7941 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
7942 } else {
Kenny Root447106f2011-03-23 11:00:15 -07007943 NativeLibraryHelper.copyNativeBinariesLI(new File(
7944 newCodePath), new File(newNativePath));
Kenny Root6a6b0072010-10-07 16:46:10 -07007945 }
7946 } else {
7947 if (mInstaller.linkNativeLibraryDirectory(
7948 pkg.applicationInfo.dataDir, newNativePath) < 0) {
7949 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
7950 }
7951 }
7952
7953 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
7954 pkg.mPath = newCodePath;
7955 // Move dex files around
7956 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
7957 // Moving of dex files failed. Set
7958 // error code and abort move.
7959 pkg.mPath = pkg.mScanPath;
7960 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
7961 }
7962 }
7963
7964 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Kenny Root447106f2011-03-23 11:00:15 -07007965 pkg.mScanPath = newCodePath;
7966 pkg.applicationInfo.sourceDir = newCodePath;
7967 pkg.applicationInfo.publicSourceDir = newResPath;
7968 pkg.applicationInfo.nativeLibraryDir = newNativePath;
7969 PackageSetting ps = (PackageSetting) pkg.mExtras;
7970 ps.codePath = new File(pkg.applicationInfo.sourceDir);
7971 ps.codePathString = ps.codePath.getPath();
7972 ps.resourcePath = new File(
7973 pkg.applicationInfo.publicSourceDir);
7974 ps.resourcePathString = ps.resourcePath.getPath();
7975 ps.nativeLibraryPathString = newNativePath;
7976 // Set the application info flag
7977 // correctly.
7978 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
7979 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
7980 } else {
7981 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
7982 }
7983 ps.setFlags(pkg.applicationInfo.flags);
7984 mAppDirs.remove(oldCodePath);
7985 mAppDirs.put(newCodePath, pkg);
7986 // Persist settings
7987 mSettings.writeLPr();
7988 }
7989 }
7990 }
7991 }
7992 // Send resources available broadcast
7993 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
7994 }
7995 }
7996 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
7997 // Clean up failed installation
7998 if (mp.targetArgs != null) {
7999 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
8000 }
8001 } else {
8002 // Force a gc to clear things up.
8003 Runtime.getRuntime().gc();
8004 // Delete older code
8005 synchronized (mInstallLock) {
8006 mp.srcArgs.doPostDeleteLI(true);
8007 }
8008 }
Kenny Rootdeb11262010-08-02 11:36:21 -07008009
Kenny Root447106f2011-03-23 11:00:15 -07008010 // Allow more operations on this file if we didn't fail because
8011 // an operation was already pending for this package.
8012 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
8013 synchronized (mPackages) {
8014 PackageParser.Package pkg = mPackages.get(mp.packageName);
8015 if (pkg != null) {
8016 pkg.mOperationPending = false;
Kenny Rootdeb11262010-08-02 11:36:21 -07008017 }
8018 }
Kenny Root447106f2011-03-23 11:00:15 -07008019 }
Kenny Rootdeb11262010-08-02 11:36:21 -07008020
Kenny Root447106f2011-03-23 11:00:15 -07008021 IPackageMoveObserver observer = mp.observer;
8022 if (observer != null) {
8023 try {
8024 observer.packageMoved(mp.packageName, returnCode);
8025 } catch (RemoteException e) {
8026 Log.i(TAG, "Observer no longer exists.");
8027 }
8028 }
8029 }
8030 });
8031 }
8032
8033 public boolean setInstallLocation(int loc) {
8034 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
8035 null);
8036 if (getInstallLocation() == loc) {
8037 return true;
8038 }
8039 if (loc == PackageHelper.APP_INSTALL_AUTO || loc == PackageHelper.APP_INSTALL_INTERNAL
8040 || loc == PackageHelper.APP_INSTALL_EXTERNAL) {
8041 android.provider.Settings.System.putInt(mContext.getContentResolver(),
8042 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
8043 return true;
8044 }
8045 return false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08008046 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -07008047
Kenny Root447106f2011-03-23 11:00:15 -07008048 public int getInstallLocation() {
8049 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
8050 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION,
8051 PackageHelper.APP_INSTALL_AUTO);
8052 }
Amith Yamasani0b285492011-04-14 17:35:23 -07008053
8054 public UserInfo createUser(String name, int flags) {
8055 UserInfo userInfo = mUserManager.createUser(name, flags, getInstalledApplications(0));
8056 return userInfo;
8057 }
8058
8059 public boolean removeUser(int userId) {
8060 if (userId == 0) {
8061 return false;
8062 }
8063 mUserManager.removeUser(userId);
8064 return true;
8065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066}