blob: 286463d22a08bfe1d940b2384f2e0a9ae9bc8d8c [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
17package com.android.server;
18
Jason parks1125d782011-01-12 09:47:26 -060019import 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.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070028import com.android.internal.util.JournaledFile;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080029import com.android.internal.util.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.app.ActivityManagerNative;
32import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080033import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080034import android.app.backup.IBackupManager;
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070035import android.content.ComponentName;
Jason parks1125d782011-01-12 09:47:26 -060036import android.content.Context;
Dianne Hackbornecb0e632010-04-07 20:22:55 -070037import android.content.IIntentReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.Intent;
39import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070040import android.content.IntentSender;
41import android.content.IntentSender.SendIntentException;
Jason parks1125d782011-01-12 09:47:26 -060042import android.content.ServiceConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.pm.ActivityInfo;
44import android.content.pm.ApplicationInfo;
45import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070046import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.content.pm.IPackageDataObserver;
48import android.content.pm.IPackageDeleteObserver;
49import android.content.pm.IPackageInstallObserver;
50import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080051import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.content.pm.IPackageStatsObserver;
53import android.content.pm.InstrumentationInfo;
54import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080055import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.content.pm.PackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.content.pm.PackageParser;
Jason parks1125d782011-01-12 09:47:26 -060058import android.content.pm.PackageStats;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.pm.PermissionGroupInfo;
Jason parks1125d782011-01-12 09:47:26 -060060import android.content.pm.PermissionInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.content.pm.ProviderInfo;
62import android.content.pm.ResolveInfo;
63import android.content.pm.ServiceInfo;
64import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.net.Uri;
66import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070067import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080069import android.os.Debug;
Jason parks1125d782011-01-12 09:47:26 -060070import android.os.Environment;
71import android.os.FileObserver;
72import android.os.FileUtils;
73import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080075import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070076import android.os.Looper;
77import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.os.Parcel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.ParcelFileDescriptor;
80import android.os.Process;
Jason parks1125d782011-01-12 09:47:26 -060081import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.ServiceManager;
83import android.os.SystemClock;
84import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080085import android.security.SystemKeyStore;
Jason parks1125d782011-01-12 09:47:26 -060086import android.util.Config;
87import android.util.DisplayMetrics;
88import android.util.EventLog;
89import android.util.Log;
90import android.util.LogPrinter;
91import android.util.Slog;
92import android.util.SparseArray;
93import android.util.Xml;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.view.Display;
95import android.view.WindowManager;
96
Kenny Root9f306d72010-09-26 11:19:47 -070097import java.io.BufferedOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import java.io.File;
99import java.io.FileDescriptor;
100import java.io.FileInputStream;
101import java.io.FileNotFoundException;
102import java.io.FileOutputStream;
103import java.io.FileReader;
104import java.io.FilenameFilter;
105import java.io.IOException;
106import java.io.InputStream;
107import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800108import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800109import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.util.ArrayList;
111import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700112import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.util.Collections;
114import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800115import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.util.Enumeration;
117import java.util.HashMap;
118import java.util.HashSet;
119import java.util.Iterator;
120import java.util.List;
121import java.util.Map;
122import java.util.Set;
123import java.util.zip.ZipEntry;
124import java.util.zip.ZipFile;
125import java.util.zip.ZipOutputStream;
126
Jason parks1125d782011-01-12 09:47:26 -0600127import org.xmlpull.v1.XmlPullParser;
128import org.xmlpull.v1.XmlPullParserException;
129import org.xmlpull.v1.XmlSerializer;
130
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700131/**
132 * Keep track of all those .apks everywhere.
133 *
134 * This is very central to the platform's security; please run the unit
135 * tests whenever making modifications here:
136 *
137mmm frameworks/base/tests/AndroidTests
138adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
139adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
140 *
141 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142class PackageManagerService extends IPackageManager.Stub {
143 private static final String TAG = "PackageManager";
144 private static final boolean DEBUG_SETTINGS = false;
145 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800146 private static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800147 private static final boolean DEBUG_INSTALL = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148
149 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
150 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400151 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700152 private static final int NFC_UID = Process.NFC_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 private static final int FIRST_APPLICATION_UID =
154 Process.FIRST_APPLICATION_UID;
155 private static final int MAX_APPLICATION_UIDS = 1000;
156
157 private static final boolean SHOW_INFO = false;
158
159 private static final boolean GET_CERTIFICATES = true;
160
Oscar Montemayora8529f62009-11-18 10:14:20 -0800161 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 private static final int REMOVE_EVENTS =
164 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
165 private static final int ADD_EVENTS =
166 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
167
168 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800169 // Suffix used during package installation when copying/moving
170 // package apks to install directory.
171 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -0800173 /**
174 * Indicates the state of installation. Used by PackageManager to
175 * figure out incomplete installations. Say a package is being installed
176 * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
177 * the package installation is successful or unsuccesful lin which case
178 * the PackageManager will no longer maintain state information associated
179 * with the package. If some exception(like device freeze or battery being
180 * pulled out) occurs during installation of a package, the PackageManager
181 * needs this information to clean up the previously failed installation.
182 */
183 private static final int PKG_INSTALL_INCOMPLETE = 0;
184 private static final int PKG_INSTALL_COMPLETE = 1;
185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 static final int SCAN_MONITOR = 1<<0;
187 static final int SCAN_NO_DEX = 1<<1;
188 static final int SCAN_FORCE_DEX = 1<<2;
189 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800190 static final int SCAN_NEW_INSTALL = 1<<4;
191 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700192 static final int SCAN_UPDATE_TIME = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700194 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700195
196 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
197
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800198 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700199 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800200 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700201
Kenny Root85387d72010-08-26 10:13:11 -0700202 private static final String LIB_DIR_NAME = "lib";
203
Kenny Rootc78a8072010-07-27 15:18:38 -0700204 static final String mTempContainerPrefix = "smdl2tmp";
205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
207 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700208 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209
Dianne Hackborn851a5412009-05-08 12:06:44 -0700210 final int mSdkVersion = Build.VERSION.SDK_INT;
211 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
212 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 final Context mContext;
215 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700216 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 final DisplayMetrics mMetrics;
218 final int mDefParseFlags;
219 final String[] mSeparateProcesses;
220
221 // This is where all application persistent data goes.
222 final File mAppDataDir;
223
Oscar Montemayora8529f62009-11-18 10:14:20 -0800224 // If Encrypted File System feature is enabled, all application persistent data
225 // should go here instead.
226 final File mSecureAppDataDir;
227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 // This is the object monitoring the framework dir.
229 final FileObserver mFrameworkInstallObserver;
230
231 // This is the object monitoring the system app dir.
232 final FileObserver mSystemInstallObserver;
233
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700234 // This is the object monitoring the system app dir.
235 final FileObserver mVendorInstallObserver;
236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 // This is the object monitoring mAppInstallDir.
238 final FileObserver mAppInstallObserver;
239
240 // This is the object monitoring mDrmAppPrivateInstallDir.
241 final FileObserver mDrmAppInstallObserver;
242
243 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
244 // LOCK HELD. Can be called with mInstallLock held.
245 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 final File mFrameworkDir;
248 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700249 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700251 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
254 // apps.
255 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 // Lock for state used when installing and doing other long running
260 // operations. Methods that must be called with this lock held have
261 // the prefix "LI".
262 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // These are the directories in the 3rd party applications installed dir
265 // that we have currently loaded packages from. Keys are the application's
266 // installed zip file (absolute codePath), and values are Package.
267 final HashMap<String, PackageParser.Package> mAppDirs =
268 new HashMap<String, PackageParser.Package>();
269
270 // Information for the parser to write more useful error messages.
271 File mScanningPath;
272 int mLastScanError;
273
274 final int[] mOutPermissions = new int[3];
275
276 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 // Keys are String (package name), values are Package. This also serves
279 // as the lock for the global state. Methods that must be called with
280 // this lock held have the prefix "LP".
281 final HashMap<String, PackageParser.Package> mPackages =
282 new HashMap<String, PackageParser.Package>();
283
284 final Settings mSettings;
285 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
288 int[] mGlobalGids;
289
290 // These are the built-in uid -> permission mappings that were read from the
291 // etc/permissions.xml file.
292 final SparseArray<HashSet<String>> mSystemPermissions =
293 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 // These are the built-in shared libraries that were read from the
296 // etc/permissions.xml file.
297 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800298
Dianne Hackborn49237342009-08-27 20:08:01 -0700299 // Temporary for building the final shared libraries for an .apk.
300 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800301
Dianne Hackborn49237342009-08-27 20:08:01 -0700302 // These are the features this devices supports that were read from the
303 // etc/permissions.xml file.
304 final HashMap<String, FeatureInfo> mAvailableFeatures =
305 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 // All available activities, for your resolving pleasure.
308 final ActivityIntentResolver mActivities =
309 new ActivityIntentResolver();
310
311 // All available receivers, for your resolving pleasure.
312 final ActivityIntentResolver mReceivers =
313 new ActivityIntentResolver();
314
315 // All available services, for your resolving pleasure.
316 final ServiceIntentResolver mServices = new ServiceIntentResolver();
317
318 // Keys are String (provider class name), values are Provider.
319 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
320 new HashMap<ComponentName, PackageParser.Provider>();
321
322 // Mapping from provider base names (first directory in content URI codePath)
323 // to the provider information.
324 final HashMap<String, PackageParser.Provider> mProviders =
325 new HashMap<String, PackageParser.Provider>();
326
327 // Mapping from instrumentation class names to info about them.
328 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
329 new HashMap<ComponentName, PackageParser.Instrumentation>();
330
331 // Mapping from permission names to info about them.
332 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
333 new HashMap<String, PackageParser.PermissionGroup>();
334
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800335 // Packages whose data we have transfered into another package, thus
336 // should no longer exist.
337 final HashSet<String> mTransferedPackages = new HashSet<String>();
338
Dianne Hackborn854060af2009-07-09 18:14:31 -0700339 // Broadcast actions that are only available to the system.
340 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 boolean mSystemReady;
343 boolean mSafeMode;
344 boolean mHasSystemUidErrors;
345
346 ApplicationInfo mAndroidApplication;
347 final ActivityInfo mResolveActivity = new ActivityInfo();
348 final ResolveInfo mResolveInfo = new ResolveInfo();
349 ComponentName mResolveComponentName;
350 PackageParser.Package mPlatformPackage;
351
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700352 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800353 final HashMap<String, ArrayList<String>> mPendingBroadcasts
354 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800355 // Service Connection to remote media container service to copy
356 // package uri's from external media onto secure containers
357 // or internal storage.
358 private IMediaContainerService mContainerService = null;
359
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700360 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800361 static final int MCS_BOUND = 3;
362 static final int END_COPY = 4;
363 static final int INIT_COPY = 5;
364 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800365 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800366 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800367 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800368 static final int MCS_RECONNECT = 10;
369 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700370 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700371 static final int WRITE_SETTINGS = 13;
372
373 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800374
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700375 // Delay time in millisecs
376 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800377 final private DefaultContainerConnection mDefContainerConn =
378 new DefaultContainerConnection();
379 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800380 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800381 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800382 IMediaContainerService imcs =
383 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800384 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800385 }
386
387 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800388 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800389 }
390 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700391
Christopher Tate1bb69062010-02-19 17:02:12 -0800392 // Recordkeeping of restore-after-install operations that are currently in flight
393 // between the Package Manager and the Backup Manager
394 class PostInstallData {
395 public InstallArgs args;
396 public PackageInstalledInfo res;
397
398 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
399 args = _a;
400 res = _r;
401 }
402 };
403 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
404 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
405
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700406 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800407 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800408 final ArrayList<HandlerParams> mPendingInstalls =
409 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800410
411 private boolean connectToService() {
412 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
413 " DefaultContainerService");
414 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700415 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800416 if (mContext.bindService(service, mDefContainerConn,
417 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700418 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800419 mBound = true;
420 return true;
421 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700422 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800423 return false;
424 }
425
426 private void disconnectService() {
427 mContainerService = null;
428 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700429 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800430 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700431 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800432 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800433
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700434 PackageHandler(Looper looper) {
435 super(looper);
436 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700437
Jason parks1125d782011-01-12 09:47:26 -0600438 @Override
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700439 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700440 try {
441 doHandleMessage(msg);
442 } finally {
443 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
444 }
445 }
446
447 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700448 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800449 case INIT_COPY: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800450 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800451 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800452 int idx = mPendingInstalls.size();
453 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
454 // If a bind was already initiated we dont really
455 // need to do anything. The pending install
456 // will be processed later on.
457 if (!mBound) {
458 // If this is the only one pending we might
459 // have to bind to the service again.
460 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800461 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800462 params.serviceError();
463 return;
464 } else {
465 // Once we bind to the service, the first
466 // pending request will be processed.
467 mPendingInstalls.add(idx, params);
468 }
469 } else {
470 mPendingInstalls.add(idx, params);
471 // Already bound to the service. Just make
472 // sure we trigger off processing the first request.
473 if (idx == 0) {
474 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800475 }
476 }
477 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800478 }
479 case MCS_BOUND: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800480 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800481 if (msg.obj != null) {
482 mContainerService = (IMediaContainerService) msg.obj;
483 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800484 if (mContainerService == null) {
485 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800486 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800487 for (HandlerParams params : mPendingInstalls) {
488 mPendingInstalls.remove(0);
489 // Indicate service bind error
490 params.serviceError();
491 }
492 mPendingInstalls.clear();
493 } else if (mPendingInstalls.size() > 0) {
494 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800495 if (params != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800496 params.startCopy();
497 }
498 } else {
499 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800500 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800501 }
502 break;
503 }
504 case MCS_RECONNECT : {
505 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
506 if (mPendingInstalls.size() > 0) {
507 if (mBound) {
508 disconnectService();
509 }
510 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800511 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800512 for (HandlerParams params : mPendingInstalls) {
513 mPendingInstalls.remove(0);
514 // Indicate service bind error
515 params.serviceError();
516 }
517 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800518 }
519 }
520 break;
521 }
522 case MCS_UNBIND : {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800523 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
524 // Delete pending install
525 if (mPendingInstalls.size() > 0) {
526 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800527 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800528 if (mPendingInstalls.size() == 0) {
529 if (mBound) {
530 disconnectService();
531 }
532 } else {
533 // There are more pending requests in queue.
534 // Just post MCS_BOUND message to trigger processing
535 // of next pending install.
536 mHandler.sendEmptyMessage(MCS_BOUND);
537 }
538 break;
539 }
540 case MCS_GIVE_UP: {
541 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
542 HandlerParams params = mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800543 break;
544 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700545 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800546 String packages[];
547 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700548 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700549 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700550 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700551 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800552 if (mPendingBroadcasts == null) {
553 return;
554 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700555 size = mPendingBroadcasts.size();
556 if (size <= 0) {
557 // Nothing to be done. Just return
558 return;
559 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800560 packages = new String[size];
561 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700562 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800563 Iterator<HashMap.Entry<String, ArrayList<String>>>
564 it = mPendingBroadcasts.entrySet().iterator();
565 int i = 0;
566 while (it.hasNext() && i < size) {
567 HashMap.Entry<String, ArrayList<String>> ent = it.next();
568 packages[i] = ent.getKey();
569 components[i] = ent.getValue();
570 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700571 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800572 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700573 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800574 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700575 mPendingBroadcasts.clear();
576 }
577 // Send broadcasts
578 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800579 sendPackageChangedBroadcast(packages[i], true,
Jason parks1125d782011-01-12 09:47:26 -0600580 components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700581 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700582 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700583 break;
584 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800585 case START_CLEANING_PACKAGE: {
586 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700587 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800588 synchronized (mPackages) {
589 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
590 mSettings.mPackagesToBeCleaned.add(packageName);
591 }
592 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700593 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800594 startCleaningPackages();
595 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800596 case POST_INSTALL: {
597 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
598 PostInstallData data = mRunningInstalls.get(msg.arg1);
599 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700600 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800601
602 if (data != null) {
603 InstallArgs args = data.args;
604 PackageInstalledInfo res = data.res;
605
606 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700607 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800608 Bundle extras = new Bundle(1);
609 extras.putInt(Intent.EXTRA_UID, res.uid);
610 final boolean update = res.removedInfo.removedPackage != null;
611 if (update) {
612 extras.putBoolean(Intent.EXTRA_REPLACING, true);
613 }
614 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
615 res.pkg.applicationInfo.packageName,
Dianne Hackbornecb0e632010-04-07 20:22:55 -0700616 extras, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800617 if (update) {
618 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
619 res.pkg.applicationInfo.packageName,
Dianne Hackbornecb0e632010-04-07 20:22:55 -0700620 extras, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800621 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700622 if (res.removedInfo.args != null) {
623 // Remove the replaced package's older resources safely now
624 deleteOld = true;
625 }
626 }
627 // Force a gc to clear up things
628 Runtime.getRuntime().gc();
629 // We delete after a gc for applications on sdcard.
630 if (deleteOld) {
631 synchronized (mInstallLock) {
632 res.removedInfo.args.doPostDeleteLI(true);
633 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800634 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800635 if (args.observer != null) {
636 try {
637 args.observer.packageInstalled(res.name, res.returnCode);
638 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800639 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800640 }
641 }
642 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800643 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800644 }
645 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700646 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700647 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
648 boolean reportStatus = msg.arg1 == 1;
649 boolean doGc = msg.arg2 == 1;
650 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
651 if (doGc) {
652 // Force a gc to clear up stale containers.
653 Runtime.getRuntime().gc();
654 }
655 if (msg.obj != null) {
656 Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
657 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
658 // Unload containers
659 unloadAllContainers(args);
660 }
661 if (reportStatus) {
662 try {
663 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
664 PackageHelper.getMountService().finishMediaUpdate();
665 } catch (RemoteException e) {
666 Log.e(TAG, "MountService not running?");
667 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700668 }
669 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700670 case WRITE_SETTINGS: {
671 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
672 synchronized (mPackages) {
673 removeMessages(WRITE_SETTINGS);
674 mSettings.writeLP();
675 }
676 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
677 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700678 }
679 }
680 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800681
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700682 void scheduleWriteSettingsLocked() {
683 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
684 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
685 }
686 }
687
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800688 static boolean installOnSd(int flags) {
689 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700690 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800691 return false;
692 }
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700693 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
694 return true;
695 }
696 return false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800697 }
698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 public static final IPackageManager main(Context context, boolean factoryTest) {
700 PackageManagerService m = new PackageManagerService(context, factoryTest);
701 ServiceManager.addService("package", m);
702 return m;
703 }
704
705 static String[] splitString(String str, char sep) {
706 int count = 1;
707 int i = 0;
708 while ((i=str.indexOf(sep, i)) >= 0) {
709 count++;
710 i++;
711 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 String[] res = new String[count];
714 i=0;
715 count = 0;
716 int lastI=0;
717 while ((i=str.indexOf(sep, i)) >= 0) {
718 res[count] = str.substring(lastI, i);
719 count++;
720 i++;
721 lastI = i;
722 }
723 res[count] = str.substring(lastI, str.length());
724 return res;
725 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800728 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800732 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 mContext = context;
736 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700737 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 mMetrics = new DisplayMetrics();
739 mSettings = new Settings();
740 mSettings.addSharedUserLP("android.uid.system",
741 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
742 mSettings.addSharedUserLP("android.uid.phone",
743 MULTIPLE_APPLICATION_UIDS
744 ? RADIO_UID : FIRST_APPLICATION_UID,
745 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400746 mSettings.addSharedUserLP("android.uid.log",
747 MULTIPLE_APPLICATION_UIDS
748 ? LOG_UID : FIRST_APPLICATION_UID,
749 ApplicationInfo.FLAG_SYSTEM);
Nick Pellycd0e8392010-10-13 17:25:24 -0700750 mSettings.addSharedUserLP("android.uid.nfc",
751 MULTIPLE_APPLICATION_UIDS
752 ? NFC_UID : FIRST_APPLICATION_UID,
753 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754
755 String separateProcesses = SystemProperties.get("debug.separate_processes");
756 if (separateProcesses != null && separateProcesses.length() > 0) {
757 if ("*".equals(separateProcesses)) {
758 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
759 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800760 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 } else {
762 mDefParseFlags = 0;
763 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800764 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 + separateProcesses);
766 }
767 } else {
768 mDefParseFlags = 0;
769 mSeparateProcesses = null;
770 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 Installer installer = new Installer();
773 // Little hacky thing to check if installd is here, to determine
774 // whether we are running on the simulator and thus need to take
775 // care of building the /data file structure ourself.
776 // (apparently the sim now has a working installer)
777 if (installer.ping() && Process.supportsProcesses()) {
778 mInstaller = installer;
779 } else {
780 mInstaller = null;
781 }
782
783 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
784 Display d = wm.getDefaultDisplay();
785 d.getMetrics(mMetrics);
786
787 synchronized (mInstallLock) {
788 synchronized (mPackages) {
789 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700790 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 File dataDir = Environment.getDataDirectory();
793 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800794 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
796
797 if (mInstaller == null) {
798 // Make sure these dirs exist, when we are running in
799 // the simulator.
800 // Make a wide-open directory for random misc stuff.
801 File miscDir = new File(dataDir, "misc");
802 miscDir.mkdirs();
803 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800804 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 mDrmAppPrivateInstallDir.mkdirs();
806 }
807
808 readPermissions();
809
810 mRestoredSettings = mSettings.readLP();
811 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800812
813 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800815
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800816 // Set flag to monitor and not change apk file paths when
817 // scanning install directories.
818 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700819 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800820 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800821 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700822 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700827 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700830 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 /**
833 * Out of paranoia, ensure that everything in the boot class
834 * path has been dexed.
835 */
836 String bootClassPath = System.getProperty("java.boot.class.path");
837 if (bootClassPath != null) {
838 String[] paths = splitString(bootClassPath, ':');
839 for (int i=0; i<paths.length; i++) {
840 try {
841 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
842 libFiles.add(paths[i]);
843 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700844 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 }
846 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800847 Slog.w(TAG, "Boot class path not found: " + paths[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800849 Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 }
851 }
852 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800853 Slog.w(TAG, "No BOOTCLASSPATH found!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 /**
857 * Also ensure all external libraries have had dexopt run on them.
858 */
859 if (mSharedLibraries.size() > 0) {
860 Iterator<String> libs = mSharedLibraries.values().iterator();
861 while (libs.hasNext()) {
862 String lib = libs.next();
863 try {
864 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
865 libFiles.add(lib);
866 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700867 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 }
869 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800870 Slog.w(TAG, "Library not found: " + lib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800872 Slog.w(TAG, "Exception reading library: " + lib, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
874 }
875 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 // Gross hack for now: we know this file doesn't contain any
878 // code, so don't dexopt it to avoid the resulting log spew.
879 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 /**
882 * And there are a number of commands implemented in Java, which
883 * we currently need to do the dexopt on so that they can be
884 * run from a non-root shell.
885 */
886 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700887 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 for (int i=0; i<frameworkFiles.length; i++) {
889 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
890 String path = libPath.getPath();
891 // Skip the file if we alrady did it.
892 if (libFiles.contains(path)) {
893 continue;
894 }
895 // Skip the file if it is not a type we want to dexopt.
896 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
897 continue;
898 }
899 try {
900 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
901 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700902 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903 }
904 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800905 Slog.w(TAG, "Jar not found: " + path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800907 Slog.w(TAG, "Exception reading jar: " + path, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 }
909 }
910 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800911
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700912 if (didDexOpt) {
913 // If we had to do a dexopt of one of the previous
914 // things, then something on the system has changed.
915 // Consider this significant, and wipe away all other
916 // existing dexopt files to ensure we don't leave any
917 // dangling around.
918 String[] files = mDalvikCacheDir.list();
919 if (files != null) {
920 for (int i=0; i<files.length; i++) {
921 String fn = files[i];
922 if (fn.startsWith("data@app@")
923 || fn.startsWith("data@app-private@")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800924 Slog.i(TAG, "Pruning dalvik file: " + fn);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700925 (new File(mDalvikCacheDir, fn)).delete();
926 }
927 }
928 }
929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800931
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800932 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 mFrameworkInstallObserver = new AppDirObserver(
934 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
935 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700936 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
937 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700938 scanMode | SCAN_NO_DEX, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800939
940 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
942 mSystemInstallObserver = new AppDirObserver(
943 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
944 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700945 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700946 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800947
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700948 // Collect all vendor packages.
949 mVendorAppDir = new File("/vendor/app");
950 mVendorInstallObserver = new AppDirObserver(
951 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
952 mVendorInstallObserver.startWatching();
953 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700954 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700955
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800956 if (mInstaller != null) {
957 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
958 mInstaller.moveFiles();
959 }
960
961 // Prune any system packages that no longer exist.
962 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
963 while (psit.hasNext()) {
964 PackageSetting ps = psit.next();
965 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800966 && !mPackages.containsKey(ps.name)
967 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800968 psit.remove();
969 String msg = "System package " + ps.name
970 + " no longer exists; wiping its data";
971 reportSettingsProblem(Log.WARN, msg);
972 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -0600973 mInstaller.remove(ps.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800974 }
975 }
976 }
977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 mAppInstallDir = new File(dataDir, "app");
979 if (mInstaller == null) {
980 // Make sure these dirs exist, when we are running in
981 // the simulator.
982 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
983 }
984 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800985 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 //clean up list
987 for(int i = 0; i < deletePkgsList.size(); i++) {
988 //clean up here
989 cleanupInstallFailedPackage(deletePkgsList.get(i));
990 }
991 //delete tmp files
992 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800993
994 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 SystemClock.uptimeMillis());
996 mAppInstallObserver = new AppDirObserver(
997 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
998 mAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700999 scanDirLI(mAppInstallDir, 0, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000
1001 mDrmAppInstallObserver = new AppDirObserver(
1002 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1003 mDrmAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001004 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1005 scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001007 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001009 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1011 + " seconds");
1012
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001013 // If the platform SDK has changed since the last time we booted,
1014 // we need to re-grant app permission to catch any new ones that
1015 // appear. This is really a hack, and means that apps can in some
1016 // cases get permissions that the user didn't initially explicitly
1017 // allow... it would be nice to have some better way to handle
1018 // this situation.
1019 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1020 != mSdkVersion;
1021 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1022 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1023 + "; regranting permissions for internal storage");
1024 mSettings.mInternalSdkPlatform = mSdkVersion;
1025
Dianne Hackborn92cfa102010-04-28 11:00:44 -07001026 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027
1028 mSettings.writeLP();
1029
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001030 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 // Now after opening every single application zip, make sure they
1034 // are all flushed. Not really needed, but keeps things nice and
1035 // tidy.
1036 Runtime.getRuntime().gc();
1037 } // synchronized (mPackages)
1038 } // synchronized (mInstallLock)
1039 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 @Override
1042 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1043 throws RemoteException {
1044 try {
1045 return super.onTransact(code, data, reply, flags);
1046 } catch (RuntimeException e) {
1047 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001048 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 }
1050 throw e;
1051 }
1052 }
1053
Dianne Hackborne6620b22010-01-22 14:46:21 -08001054 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001055 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06001057 int retCode = mInstaller.remove(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001059 Slog.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -08001060 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 }
1062 } else {
1063 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -08001064 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 File dataDir = new File(pkg.applicationInfo.dataDir);
1066 dataDir.delete();
1067 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001068 if (ps.codePath != null) {
1069 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001070 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001071 }
1072 }
1073 if (ps.resourcePath != null) {
1074 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001075 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001076 }
1077 }
1078 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 }
1080
1081 void readPermissions() {
1082 // Read permissions from .../etc/permission directory.
1083 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1084 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001085 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 return;
1087 }
1088 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001089 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 return;
1091 }
1092
1093 // Iterate over the files in the directory and scan .xml files
1094 for (File f : libraryDir.listFiles()) {
1095 // We'll read platform.xml last
1096 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1097 continue;
1098 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001101 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 continue;
1103 }
1104 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001105 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 continue;
1107 }
1108
1109 readPermissionsFromXml(f);
1110 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1113 final File permFile = new File(Environment.getRootDirectory(),
1114 "etc/permissions/platform.xml");
1115 readPermissionsFromXml(permFile);
1116 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001117
1118 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 FileReader permReader = null;
1120 try {
1121 permReader = new FileReader(permFile);
1122 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001123 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 return;
1125 }
1126
1127 try {
1128 XmlPullParser parser = Xml.newPullParser();
1129 parser.setInput(permReader);
1130
1131 XmlUtils.beginDocument(parser, "permissions");
1132
1133 while (true) {
1134 XmlUtils.nextElement(parser);
1135 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1136 break;
1137 }
1138
1139 String name = parser.getName();
1140 if ("group".equals(name)) {
1141 String gidStr = parser.getAttributeValue(null, "gid");
1142 if (gidStr != null) {
1143 int gid = Integer.parseInt(gidStr);
1144 mGlobalGids = appendInt(mGlobalGids, gid);
1145 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001146 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 + parser.getPositionDescription());
1148 }
1149
1150 XmlUtils.skipCurrentTag(parser);
1151 continue;
1152 } else if ("permission".equals(name)) {
1153 String perm = parser.getAttributeValue(null, "name");
1154 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001155 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 + parser.getPositionDescription());
1157 XmlUtils.skipCurrentTag(parser);
1158 continue;
1159 }
1160 perm = perm.intern();
1161 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 } else if ("assign-permission".equals(name)) {
1164 String perm = parser.getAttributeValue(null, "name");
1165 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001166 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 + parser.getPositionDescription());
1168 XmlUtils.skipCurrentTag(parser);
1169 continue;
1170 }
1171 String uidStr = parser.getAttributeValue(null, "uid");
1172 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001173 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 + parser.getPositionDescription());
1175 XmlUtils.skipCurrentTag(parser);
1176 continue;
1177 }
1178 int uid = Process.getUidForName(uidStr);
1179 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001180 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 + uidStr + "\" at "
1182 + parser.getPositionDescription());
1183 XmlUtils.skipCurrentTag(parser);
1184 continue;
1185 }
1186 perm = perm.intern();
1187 HashSet<String> perms = mSystemPermissions.get(uid);
1188 if (perms == null) {
1189 perms = new HashSet<String>();
1190 mSystemPermissions.put(uid, perms);
1191 }
1192 perms.add(perm);
1193 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 } else if ("library".equals(name)) {
1196 String lname = parser.getAttributeValue(null, "name");
1197 String lfile = parser.getAttributeValue(null, "file");
1198 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001199 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 + parser.getPositionDescription());
1201 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001202 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 + parser.getPositionDescription());
1204 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001205 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001206 mSharedLibraries.put(lname, lfile);
1207 }
1208 XmlUtils.skipCurrentTag(parser);
1209 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001210
Dianne Hackborn49237342009-08-27 20:08:01 -07001211 } else if ("feature".equals(name)) {
1212 String fname = parser.getAttributeValue(null, "name");
1213 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001214 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001215 + parser.getPositionDescription());
1216 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001217 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001218 FeatureInfo fi = new FeatureInfo();
1219 fi.name = fname;
1220 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 }
1222 XmlUtils.skipCurrentTag(parser);
1223 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 } else {
1226 XmlUtils.skipCurrentTag(parser);
1227 continue;
1228 }
1229
1230 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001231 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001233 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001235 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 }
1237 }
1238
1239 void readPermission(XmlPullParser parser, String name)
1240 throws IOException, XmlPullParserException {
1241
1242 name = name.intern();
1243
1244 BasePermission bp = mSettings.mPermissions.get(name);
1245 if (bp == null) {
1246 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1247 mSettings.mPermissions.put(name, bp);
1248 }
1249 int outerDepth = parser.getDepth();
1250 int type;
1251 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1252 && (type != XmlPullParser.END_TAG
1253 || parser.getDepth() > outerDepth)) {
1254 if (type == XmlPullParser.END_TAG
1255 || type == XmlPullParser.TEXT) {
1256 continue;
1257 }
1258
1259 String tagName = parser.getName();
1260 if ("group".equals(tagName)) {
1261 String gidStr = parser.getAttributeValue(null, "gid");
1262 if (gidStr != null) {
1263 int gid = Process.getGidForName(gidStr);
1264 bp.gids = appendInt(bp.gids, gid);
1265 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001266 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 + parser.getPositionDescription());
1268 }
1269 }
1270 XmlUtils.skipCurrentTag(parser);
1271 }
1272 }
1273
1274 static int[] appendInt(int[] cur, int val) {
1275 if (cur == null) {
1276 return new int[] { val };
1277 }
1278 final int N = cur.length;
1279 for (int i=0; i<N; i++) {
1280 if (cur[i] == val) {
1281 return cur;
1282 }
1283 }
1284 int[] ret = new int[N+1];
1285 System.arraycopy(cur, 0, ret, 0, N);
1286 ret[N] = val;
1287 return ret;
1288 }
1289
1290 static int[] appendInts(int[] cur, int[] add) {
1291 if (add == null) return cur;
1292 if (cur == null) return add;
1293 final int N = add.length;
1294 for (int i=0; i<N; i++) {
1295 cur = appendInt(cur, add[i]);
1296 }
1297 return cur;
1298 }
1299
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001300 static int[] removeInt(int[] cur, int val) {
1301 if (cur == null) {
1302 return null;
1303 }
1304 final int N = cur.length;
1305 for (int i=0; i<N; i++) {
1306 if (cur[i] == val) {
1307 int[] ret = new int[N-1];
1308 if (i > 0) {
1309 System.arraycopy(cur, 0, ret, 0, i);
1310 }
1311 if (i < (N-1)) {
Jeff Brown8c8bb8b2010-04-20 17:21:47 -07001312 System.arraycopy(cur, i + 1, ret, i, N - i - 1);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001313 }
1314 return ret;
1315 }
1316 }
1317 return cur;
1318 }
1319
1320 static int[] removeInts(int[] cur, int[] rem) {
1321 if (rem == null) return cur;
1322 if (cur == null) return cur;
1323 final int N = rem.length;
1324 for (int i=0; i<N; i++) {
1325 cur = removeInt(cur, rem[i]);
1326 }
1327 return cur;
1328 }
1329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001331 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1332 // The package has been uninstalled but has retained data and resources.
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001333 return PackageParser.generatePackageInfo(p, null, flags, 0, 0);
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001334 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 final PackageSetting ps = (PackageSetting)p.mExtras;
1336 if (ps == null) {
1337 return null;
1338 }
1339 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001340 return PackageParser.generatePackageInfo(p, gp.gids, flags,
1341 ps.firstInstallTime, ps.lastUpdateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 }
1343
1344 public PackageInfo getPackageInfo(String packageName, int flags) {
1345 synchronized (mPackages) {
1346 PackageParser.Package p = mPackages.get(packageName);
1347 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001348 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 + ": " + p);
1350 if (p != null) {
1351 return generatePackageInfo(p, flags);
1352 }
1353 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1354 return generatePackageInfoFromSettingsLP(packageName, flags);
1355 }
1356 }
1357 return null;
1358 }
1359
Dianne Hackborn47096932010-02-11 15:57:09 -08001360 public String[] currentToCanonicalPackageNames(String[] names) {
1361 String[] out = new String[names.length];
1362 synchronized (mPackages) {
1363 for (int i=names.length-1; i>=0; i--) {
1364 PackageSetting ps = mSettings.mPackages.get(names[i]);
1365 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1366 }
1367 }
1368 return out;
1369 }
1370
1371 public String[] canonicalToCurrentPackageNames(String[] names) {
1372 String[] out = new String[names.length];
1373 synchronized (mPackages) {
1374 for (int i=names.length-1; i>=0; i--) {
1375 String cur = mSettings.mRenamedPackages.get(names[i]);
1376 out[i] = cur != null ? cur : names[i];
1377 }
1378 }
1379 return out;
1380 }
1381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 public int getPackageUid(String packageName) {
1383 synchronized (mPackages) {
1384 PackageParser.Package p = mPackages.get(packageName);
1385 if(p != null) {
1386 return p.applicationInfo.uid;
1387 }
1388 PackageSetting ps = mSettings.mPackages.get(packageName);
1389 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1390 return -1;
1391 }
1392 p = ps.pkg;
1393 return p != null ? p.applicationInfo.uid : -1;
1394 }
1395 }
1396
1397 public int[] getPackageGids(String packageName) {
1398 synchronized (mPackages) {
1399 PackageParser.Package p = mPackages.get(packageName);
1400 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001401 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 + ": " + p);
1403 if (p != null) {
1404 final PackageSetting ps = (PackageSetting)p.mExtras;
1405 final SharedUserSetting suid = ps.sharedUser;
1406 return suid != null ? suid.gids : ps.gids;
1407 }
1408 }
1409 // stupid thing to indicate an error.
1410 return new int[0];
1411 }
1412
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001413 static final PermissionInfo generatePermissionInfo(
1414 BasePermission bp, int flags) {
1415 if (bp.perm != null) {
1416 return PackageParser.generatePermissionInfo(bp.perm, flags);
1417 }
1418 PermissionInfo pi = new PermissionInfo();
1419 pi.name = bp.name;
1420 pi.packageName = bp.sourcePackage;
1421 pi.nonLocalizedLabel = bp.name;
1422 pi.protectionLevel = bp.protectionLevel;
1423 return pi;
1424 }
1425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 public PermissionInfo getPermissionInfo(String name, int flags) {
1427 synchronized (mPackages) {
1428 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001429 if (p != null) {
1430 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 }
1432 return null;
1433 }
1434 }
1435
1436 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1437 synchronized (mPackages) {
1438 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1439 for (BasePermission p : mSettings.mPermissions.values()) {
1440 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001441 if (p.perm == null || p.perm.info.group == null) {
1442 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 }
1444 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001445 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1447 }
1448 }
1449 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 if (out.size() > 0) {
1452 return out;
1453 }
1454 return mPermissionGroups.containsKey(group) ? out : null;
1455 }
1456 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1459 synchronized (mPackages) {
1460 return PackageParser.generatePermissionGroupInfo(
1461 mPermissionGroups.get(name), flags);
1462 }
1463 }
1464
1465 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1466 synchronized (mPackages) {
1467 final int N = mPermissionGroups.size();
1468 ArrayList<PermissionGroupInfo> out
1469 = new ArrayList<PermissionGroupInfo>(N);
1470 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1471 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1472 }
1473 return out;
1474 }
1475 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1478 PackageSetting ps = mSettings.mPackages.get(packageName);
1479 if(ps != null) {
1480 if(ps.pkg == null) {
1481 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1482 if(pInfo != null) {
1483 return pInfo.applicationInfo;
1484 }
1485 return null;
1486 }
1487 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1488 }
1489 return null;
1490 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1493 PackageSetting ps = mSettings.mPackages.get(packageName);
1494 if(ps != null) {
1495 if(ps.pkg == null) {
1496 ps.pkg = new PackageParser.Package(packageName);
1497 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001498 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1499 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1500 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
1501 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001502 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07001503 ps.pkg.mSetEnabled = ps.enabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 }
1505 return generatePackageInfo(ps.pkg, flags);
1506 }
1507 return null;
1508 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1511 synchronized (mPackages) {
1512 PackageParser.Package p = mPackages.get(packageName);
1513 if (Config.LOGV) Log.v(
1514 TAG, "getApplicationInfo " + packageName
1515 + ": " + p);
1516 if (p != null) {
1517 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001518 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 }
1520 if ("android".equals(packageName)||"system".equals(packageName)) {
1521 return mAndroidApplication;
1522 }
1523 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1524 return generateApplicationInfoFromSettingsLP(packageName, flags);
1525 }
1526 }
1527 return null;
1528 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001529
1530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1532 mContext.enforceCallingOrSelfPermission(
1533 android.Manifest.permission.CLEAR_APP_CACHE, null);
1534 // Queue up an async operation since clearing cache may take a little while.
1535 mHandler.post(new Runnable() {
1536 public void run() {
1537 mHandler.removeCallbacks(this);
1538 int retCode = -1;
1539 if (mInstaller != null) {
1540 retCode = mInstaller.freeCache(freeStorageSize);
1541 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001542 Slog.w(TAG, "Couldn't clear application caches");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
1544 } //end if mInstaller
1545 if (observer != null) {
1546 try {
1547 observer.onRemoveCompleted(null, (retCode >= 0));
1548 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001549 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 }
1551 }
1552 }
1553 });
1554 }
1555
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001556 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001557 mContext.enforceCallingOrSelfPermission(
1558 android.Manifest.permission.CLEAR_APP_CACHE, null);
1559 // Queue up an async operation since clearing cache may take a little while.
1560 mHandler.post(new Runnable() {
1561 public void run() {
1562 mHandler.removeCallbacks(this);
1563 int retCode = -1;
1564 if (mInstaller != null) {
1565 retCode = mInstaller.freeCache(freeStorageSize);
1566 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001567 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001568 }
1569 }
1570 if(pi != null) {
1571 try {
1572 // Callback via pending intent
1573 int code = (retCode >= 0) ? 1 : 0;
1574 pi.sendIntent(null, code, null,
1575 null, null);
1576 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001577 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001578 }
1579 }
1580 }
1581 });
1582 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1585 synchronized (mPackages) {
1586 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001587
1588 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001590 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 }
1592 if (mResolveComponentName.equals(component)) {
1593 return mResolveActivity;
1594 }
1595 }
1596 return null;
1597 }
1598
1599 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1600 synchronized (mPackages) {
1601 PackageParser.Activity a = mReceivers.mActivities.get(component);
1602 if (Config.LOGV) Log.v(
1603 TAG, "getReceiverInfo " + component + ": " + a);
1604 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1605 return PackageParser.generateActivityInfo(a, flags);
1606 }
1607 }
1608 return null;
1609 }
1610
1611 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1612 synchronized (mPackages) {
1613 PackageParser.Service s = mServices.mServices.get(component);
1614 if (Config.LOGV) Log.v(
1615 TAG, "getServiceInfo " + component + ": " + s);
1616 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1617 return PackageParser.generateServiceInfo(s, flags);
1618 }
1619 }
1620 return null;
1621 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001622
Dianne Hackborn361199b2010-08-30 17:42:07 -07001623 public ProviderInfo getProviderInfo(ComponentName component, int flags) {
1624 synchronized (mPackages) {
1625 PackageParser.Provider p = mProvidersByComponent.get(component);
1626 if (Config.LOGV) Log.v(
1627 TAG, "getProviderInfo " + component + ": " + p);
1628 if (p != null && mSettings.isEnabledLP(p.info, flags)) {
1629 return PackageParser.generateProviderInfo(p, flags);
1630 }
1631 }
1632 return null;
1633 }
1634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 public String[] getSystemSharedLibraryNames() {
1636 Set<String> libSet;
1637 synchronized (mPackages) {
1638 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001639 int size = libSet.size();
1640 if (size > 0) {
1641 String[] libs = new String[size];
1642 libSet.toArray(libs);
1643 return libs;
1644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001646 return null;
1647 }
1648
1649 public FeatureInfo[] getSystemAvailableFeatures() {
1650 Collection<FeatureInfo> featSet;
1651 synchronized (mPackages) {
1652 featSet = mAvailableFeatures.values();
1653 int size = featSet.size();
1654 if (size > 0) {
1655 FeatureInfo[] features = new FeatureInfo[size+1];
1656 featSet.toArray(features);
1657 FeatureInfo fi = new FeatureInfo();
1658 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1659 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1660 features[size] = fi;
1661 return features;
1662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 }
1664 return null;
1665 }
1666
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001667 public boolean hasSystemFeature(String name) {
1668 synchronized (mPackages) {
1669 return mAvailableFeatures.containsKey(name);
1670 }
1671 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 public int checkPermission(String permName, String pkgName) {
1674 synchronized (mPackages) {
1675 PackageParser.Package p = mPackages.get(pkgName);
1676 if (p != null && p.mExtras != null) {
1677 PackageSetting ps = (PackageSetting)p.mExtras;
1678 if (ps.sharedUser != null) {
1679 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1680 return PackageManager.PERMISSION_GRANTED;
1681 }
1682 } else if (ps.grantedPermissions.contains(permName)) {
1683 return PackageManager.PERMISSION_GRANTED;
1684 }
1685 }
1686 }
1687 return PackageManager.PERMISSION_DENIED;
1688 }
1689
1690 public int checkUidPermission(String permName, int uid) {
1691 synchronized (mPackages) {
1692 Object obj = mSettings.getUserIdLP(uid);
1693 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001694 GrantedPermissions gp = (GrantedPermissions)obj;
1695 if (gp.grantedPermissions.contains(permName)) {
1696 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 }
1698 } else {
1699 HashSet<String> perms = mSystemPermissions.get(uid);
1700 if (perms != null && perms.contains(permName)) {
1701 return PackageManager.PERMISSION_GRANTED;
1702 }
1703 }
1704 }
1705 return PackageManager.PERMISSION_DENIED;
1706 }
1707
1708 private BasePermission findPermissionTreeLP(String permName) {
1709 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1710 if (permName.startsWith(bp.name) &&
1711 permName.length() > bp.name.length() &&
1712 permName.charAt(bp.name.length()) == '.') {
1713 return bp;
1714 }
1715 }
1716 return null;
1717 }
1718
1719 private BasePermission checkPermissionTreeLP(String permName) {
1720 if (permName != null) {
1721 BasePermission bp = findPermissionTreeLP(permName);
1722 if (bp != null) {
1723 if (bp.uid == Binder.getCallingUid()) {
1724 return bp;
1725 }
1726 throw new SecurityException("Calling uid "
1727 + Binder.getCallingUid()
1728 + " is not allowed to add to permission tree "
1729 + bp.name + " owned by uid " + bp.uid);
1730 }
1731 }
1732 throw new SecurityException("No permission tree found for " + permName);
1733 }
1734
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001735 static boolean compareStrings(CharSequence s1, CharSequence s2) {
1736 if (s1 == null) {
1737 return s2 == null;
1738 }
1739 if (s2 == null) {
1740 return false;
1741 }
1742 if (s1.getClass() != s2.getClass()) {
1743 return false;
1744 }
1745 return s1.equals(s2);
1746 }
1747
1748 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
1749 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07001750 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001751 if (pi1.protectionLevel != pi2.protectionLevel) return false;
1752 if (!compareStrings(pi1.name, pi2.name)) return false;
1753 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
1754 // We'll take care of setting this one.
1755 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
1756 // These are not currently stored in settings.
1757 //if (!compareStrings(pi1.group, pi2.group)) return false;
1758 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
1759 //if (pi1.labelRes != pi2.labelRes) return false;
1760 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
1761 return true;
1762 }
1763
1764 boolean addPermissionLocked(PermissionInfo info, boolean async) {
1765 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1766 throw new SecurityException("Label must be specified in permission");
1767 }
1768 BasePermission tree = checkPermissionTreeLP(info.name);
1769 BasePermission bp = mSettings.mPermissions.get(info.name);
1770 boolean added = bp == null;
1771 boolean changed = true;
1772 if (added) {
1773 bp = new BasePermission(info.name, tree.sourcePackage,
1774 BasePermission.TYPE_DYNAMIC);
1775 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1776 throw new SecurityException(
1777 "Not allowed to modify non-dynamic permission "
1778 + info.name);
1779 } else {
1780 if (bp.protectionLevel == info.protectionLevel
1781 && bp.perm.owner.equals(tree.perm.owner)
1782 && bp.uid == tree.uid
1783 && comparePermissionInfos(bp.perm.info, info)) {
1784 changed = false;
1785 }
1786 }
1787 bp.protectionLevel = info.protectionLevel;
1788 bp.perm = new PackageParser.Permission(tree.perm.owner,
1789 new PermissionInfo(info));
1790 bp.perm.info.packageName = tree.perm.info.packageName;
1791 bp.uid = tree.uid;
1792 if (added) {
1793 mSettings.mPermissions.put(info.name, bp);
1794 }
1795 if (changed) {
1796 if (!async) {
1797 mSettings.writeLP();
1798 } else {
1799 scheduleWriteSettingsLocked();
1800 }
1801 }
1802 return added;
1803 }
1804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 public boolean addPermission(PermissionInfo info) {
1806 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001807 return addPermissionLocked(info, false);
1808 }
1809 }
1810
1811 public boolean addPermissionAsync(PermissionInfo info) {
1812 synchronized (mPackages) {
1813 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 }
1815 }
1816
1817 public void removePermission(String name) {
1818 synchronized (mPackages) {
1819 checkPermissionTreeLP(name);
1820 BasePermission bp = mSettings.mPermissions.get(name);
1821 if (bp != null) {
1822 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1823 throw new SecurityException(
1824 "Not allowed to modify non-dynamic permission "
1825 + name);
1826 }
1827 mSettings.mPermissions.remove(name);
1828 mSettings.writeLP();
1829 }
1830 }
1831 }
1832
Dianne Hackborn854060af2009-07-09 18:14:31 -07001833 public boolean isProtectedBroadcast(String actionName) {
1834 synchronized (mPackages) {
1835 return mProtectedBroadcasts.contains(actionName);
1836 }
1837 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 public int checkSignatures(String pkg1, String pkg2) {
1840 synchronized (mPackages) {
1841 PackageParser.Package p1 = mPackages.get(pkg1);
1842 PackageParser.Package p2 = mPackages.get(pkg2);
1843 if (p1 == null || p1.mExtras == null
1844 || p2 == null || p2.mExtras == null) {
1845 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1846 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001847 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
1849 }
1850
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001851 public int checkUidSignatures(int uid1, int uid2) {
1852 synchronized (mPackages) {
1853 Signature[] s1;
1854 Signature[] s2;
1855 Object obj = mSettings.getUserIdLP(uid1);
1856 if (obj != null) {
1857 if (obj instanceof SharedUserSetting) {
1858 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1859 } else if (obj instanceof PackageSetting) {
1860 s1 = ((PackageSetting)obj).signatures.mSignatures;
1861 } else {
1862 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1863 }
1864 } else {
1865 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1866 }
1867 obj = mSettings.getUserIdLP(uid2);
1868 if (obj != null) {
1869 if (obj instanceof SharedUserSetting) {
1870 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1871 } else if (obj instanceof PackageSetting) {
1872 s2 = ((PackageSetting)obj).signatures.mSignatures;
1873 } else {
1874 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1875 }
1876 } else {
1877 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1878 }
1879 return checkSignaturesLP(s1, s2);
1880 }
1881 }
1882
1883 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1884 if (s1 == null) {
1885 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1887 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1888 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001889 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1891 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001892 HashSet<Signature> set1 = new HashSet<Signature>();
1893 for (Signature sig : s1) {
1894 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001896 HashSet<Signature> set2 = new HashSet<Signature>();
1897 for (Signature sig : s2) {
1898 set2.add(sig);
1899 }
1900 // Make sure s2 contains all signatures in s1.
1901 if (set1.equals(set2)) {
1902 return PackageManager.SIGNATURE_MATCH;
1903 }
1904 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 }
1906
1907 public String[] getPackagesForUid(int uid) {
1908 synchronized (mPackages) {
1909 Object obj = mSettings.getUserIdLP(uid);
1910 if (obj instanceof SharedUserSetting) {
1911 SharedUserSetting sus = (SharedUserSetting)obj;
1912 final int N = sus.packages.size();
1913 String[] res = new String[N];
1914 Iterator<PackageSetting> it = sus.packages.iterator();
1915 int i=0;
1916 while (it.hasNext()) {
1917 res[i++] = it.next().name;
1918 }
1919 return res;
1920 } else if (obj instanceof PackageSetting) {
1921 PackageSetting ps = (PackageSetting)obj;
1922 return new String[] { ps.name };
1923 }
1924 }
1925 return null;
1926 }
1927
1928 public String getNameForUid(int uid) {
1929 synchronized (mPackages) {
1930 Object obj = mSettings.getUserIdLP(uid);
1931 if (obj instanceof SharedUserSetting) {
1932 SharedUserSetting sus = (SharedUserSetting)obj;
1933 return sus.name + ":" + sus.userId;
1934 } else if (obj instanceof PackageSetting) {
1935 PackageSetting ps = (PackageSetting)obj;
1936 return ps.name;
1937 }
1938 }
1939 return null;
1940 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 public int getUidForSharedUser(String sharedUserName) {
1943 if(sharedUserName == null) {
1944 return -1;
1945 }
1946 synchronized (mPackages) {
1947 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1948 if(suid == null) {
1949 return -1;
1950 }
1951 return suid.userId;
1952 }
1953 }
1954
1955 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1956 int flags) {
1957 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001958 return chooseBestActivity(intent, resolvedType, flags, query);
1959 }
1960
Mihai Predaeae850c2009-05-13 10:13:48 +02001961 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1962 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 if (query != null) {
1964 final int N = query.size();
1965 if (N == 1) {
1966 return query.get(0);
1967 } else if (N > 1) {
1968 // If there is more than one activity with the same priority,
1969 // then let the user decide between them.
1970 ResolveInfo r0 = query.get(0);
1971 ResolveInfo r1 = query.get(1);
1972 if (false) {
1973 System.out.println(r0.activityInfo.name +
1974 "=" + r0.priority + " vs " +
1975 r1.activityInfo.name +
1976 "=" + r1.priority);
1977 }
1978 // If the first activity has a higher priority, or a different
1979 // default, then it is always desireable to pick it.
1980 if (r0.priority != r1.priority
1981 || r0.preferredOrder != r1.preferredOrder
1982 || r0.isDefault != r1.isDefault) {
1983 return query.get(0);
1984 }
1985 // If we have saved a preference for a preferred activity for
1986 // this Intent, use that.
1987 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1988 flags, query, r0.priority);
1989 if (ri != null) {
1990 return ri;
1991 }
1992 return mResolveInfo;
1993 }
1994 }
1995 return null;
1996 }
1997
1998 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1999 int flags, List<ResolveInfo> query, int priority) {
2000 synchronized (mPackages) {
2001 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2002 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002003 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2005 if (prefs != null && prefs.size() > 0) {
2006 // First figure out how good the original match set is.
2007 // We will only allow preferred activities that came
2008 // from the same match quality.
2009 int match = 0;
2010 final int N = query.size();
2011 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
2012 for (int j=0; j<N; j++) {
2013 ResolveInfo ri = query.get(j);
2014 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
2015 + ": 0x" + Integer.toHexString(match));
2016 if (ri.match > match) match = ri.match;
2017 }
2018 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
2019 + Integer.toHexString(match));
2020 match &= IntentFilter.MATCH_CATEGORY_MASK;
2021 final int M = prefs.size();
2022 for (int i=0; i<M; i++) {
2023 PreferredActivity pa = prefs.get(i);
2024 if (pa.mMatch != match) {
2025 continue;
2026 }
2027 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
2028 if (DEBUG_PREFERRED) {
2029 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002030 if (ai != null) {
2031 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2032 } else {
2033 Log.v(TAG, " null");
2034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 }
2036 if (ai != null) {
2037 for (int j=0; j<N; j++) {
2038 ResolveInfo ri = query.get(j);
2039 if (!ri.activityInfo.applicationInfo.packageName
2040 .equals(ai.applicationInfo.packageName)) {
2041 continue;
2042 }
2043 if (!ri.activityInfo.name.equals(ai.name)) {
2044 continue;
2045 }
2046
2047 // Okay we found a previously set preferred app.
2048 // If the result set is different from when this
2049 // was created, we need to clear it and re-ask the
2050 // user their preference.
2051 if (!pa.sameSet(query, priority)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002052 Slog.i(TAG, "Result set changed, dropping preferred activity for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 + intent + " type " + resolvedType);
2054 mSettings.mPreferredActivities.removeFilter(pa);
2055 return null;
2056 }
2057
2058 // Yay!
2059 return ri;
2060 }
2061 }
2062 }
2063 }
2064 }
2065 return null;
2066 }
2067
2068 public List<ResolveInfo> queryIntentActivities(Intent intent,
2069 String resolvedType, int flags) {
2070 ComponentName comp = intent.getComponent();
2071 if (comp != null) {
2072 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2073 ActivityInfo ai = getActivityInfo(comp, flags);
2074 if (ai != null) {
2075 ResolveInfo ri = new ResolveInfo();
2076 ri.activityInfo = ai;
2077 list.add(ri);
2078 }
2079 return list;
2080 }
2081
2082 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002083 String pkgName = intent.getPackage();
2084 if (pkgName == null) {
Jason parks1125d782011-01-12 09:47:26 -06002085 return mActivities.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002086 resolvedType, flags);
2087 }
2088 PackageParser.Package pkg = mPackages.get(pkgName);
2089 if (pkg != null) {
Jason parks1125d782011-01-12 09:47:26 -06002090 return mActivities.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002091 resolvedType, flags, pkg.activities);
2092 }
2093 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094 }
2095 }
2096
2097 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2098 Intent[] specifics, String[] specificTypes, Intent intent,
2099 String resolvedType, int flags) {
2100 final String resultsAction = intent.getAction();
2101
2102 List<ResolveInfo> results = queryIntentActivities(
2103 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
2104 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
2105
2106 int specificsPos = 0;
2107 int N;
2108
2109 // todo: note that the algorithm used here is O(N^2). This
2110 // isn't a problem in our current environment, but if we start running
2111 // into situations where we have more than 5 or 10 matches then this
2112 // should probably be changed to something smarter...
2113
2114 // First we go through and resolve each of the specific items
2115 // that were supplied, taking care of removing any corresponding
2116 // duplicate items in the generic resolve list.
2117 if (specifics != null) {
2118 for (int i=0; i<specifics.length; i++) {
2119 final Intent sintent = specifics[i];
2120 if (sintent == null) {
2121 continue;
2122 }
2123
2124 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
2125 String action = sintent.getAction();
2126 if (resultsAction != null && resultsAction.equals(action)) {
2127 // If this action was explicitly requested, then don't
2128 // remove things that have it.
2129 action = null;
2130 }
2131 ComponentName comp = sintent.getComponent();
2132 ResolveInfo ri = null;
2133 ActivityInfo ai = null;
2134 if (comp == null) {
2135 ri = resolveIntent(
2136 sintent,
2137 specificTypes != null ? specificTypes[i] : null,
2138 flags);
2139 if (ri == null) {
2140 continue;
2141 }
2142 if (ri == mResolveInfo) {
2143 // ACK! Must do something better with this.
2144 }
2145 ai = ri.activityInfo;
2146 comp = new ComponentName(ai.applicationInfo.packageName,
2147 ai.name);
2148 } else {
2149 ai = getActivityInfo(comp, flags);
2150 if (ai == null) {
2151 continue;
2152 }
2153 }
2154
2155 // Look for any generic query activities that are duplicates
2156 // of this specific one, and remove them from the results.
2157 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
2158 N = results.size();
2159 int j;
2160 for (j=specificsPos; j<N; j++) {
2161 ResolveInfo sri = results.get(j);
2162 if ((sri.activityInfo.name.equals(comp.getClassName())
2163 && sri.activityInfo.applicationInfo.packageName.equals(
2164 comp.getPackageName()))
2165 || (action != null && sri.filter.matchAction(action))) {
2166 results.remove(j);
2167 if (Config.LOGV) Log.v(
2168 TAG, "Removing duplicate item from " + j
2169 + " due to specific " + specificsPos);
2170 if (ri == null) {
2171 ri = sri;
2172 }
2173 j--;
2174 N--;
2175 }
2176 }
2177
2178 // Add this specific item to its proper place.
2179 if (ri == null) {
2180 ri = new ResolveInfo();
2181 ri.activityInfo = ai;
2182 }
2183 results.add(specificsPos, ri);
2184 ri.specificIndex = i;
2185 specificsPos++;
2186 }
2187 }
2188
2189 // Now we go through the remaining generic results and remove any
2190 // duplicate actions that are found here.
2191 N = results.size();
2192 for (int i=specificsPos; i<N-1; i++) {
2193 final ResolveInfo rii = results.get(i);
2194 if (rii.filter == null) {
2195 continue;
2196 }
2197
2198 // Iterate over all of the actions of this result's intent
2199 // filter... typically this should be just one.
2200 final Iterator<String> it = rii.filter.actionsIterator();
2201 if (it == null) {
2202 continue;
2203 }
2204 while (it.hasNext()) {
2205 final String action = it.next();
2206 if (resultsAction != null && resultsAction.equals(action)) {
2207 // If this action was explicitly requested, then don't
2208 // remove things that have it.
2209 continue;
2210 }
2211 for (int j=i+1; j<N; j++) {
2212 final ResolveInfo rij = results.get(j);
2213 if (rij.filter != null && rij.filter.hasAction(action)) {
2214 results.remove(j);
2215 if (Config.LOGV) Log.v(
2216 TAG, "Removing duplicate item from " + j
2217 + " due to action " + action + " at " + i);
2218 j--;
2219 N--;
2220 }
2221 }
2222 }
2223
2224 // If the caller didn't request filter information, drop it now
2225 // so we don't have to marshall/unmarshall it.
2226 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2227 rii.filter = null;
2228 }
2229 }
2230
2231 // Filter out the caller activity if so requested.
2232 if (caller != null) {
2233 N = results.size();
2234 for (int i=0; i<N; i++) {
2235 ActivityInfo ainfo = results.get(i).activityInfo;
2236 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2237 && caller.getClassName().equals(ainfo.name)) {
2238 results.remove(i);
2239 break;
2240 }
2241 }
2242 }
2243
2244 // If the caller didn't request filter information,
2245 // drop them now so we don't have to
2246 // marshall/unmarshall it.
2247 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2248 N = results.size();
2249 for (int i=0; i<N; i++) {
2250 results.get(i).filter = null;
2251 }
2252 }
2253
2254 if (Config.LOGV) Log.v(TAG, "Result: " + results);
2255 return results;
2256 }
2257
2258 public List<ResolveInfo> queryIntentReceivers(Intent intent,
2259 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002260 ComponentName comp = intent.getComponent();
2261 if (comp != null) {
2262 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2263 ActivityInfo ai = getReceiverInfo(comp, flags);
2264 if (ai != null) {
2265 ResolveInfo ri = new ResolveInfo();
2266 ri.activityInfo = ai;
2267 list.add(ri);
2268 }
2269 return list;
2270 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002273 String pkgName = intent.getPackage();
2274 if (pkgName == null) {
Jason parks1125d782011-01-12 09:47:26 -06002275 return mReceivers.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002276 resolvedType, flags);
2277 }
2278 PackageParser.Package pkg = mPackages.get(pkgName);
2279 if (pkg != null) {
Jason parks1125d782011-01-12 09:47:26 -06002280 return mReceivers.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002281 resolvedType, flags, pkg.receivers);
2282 }
2283 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 }
2285 }
2286
2287 public ResolveInfo resolveService(Intent intent, String resolvedType,
2288 int flags) {
2289 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
2290 flags);
2291 if (query != null) {
2292 if (query.size() >= 1) {
2293 // If there is more than one service with the same priority,
2294 // just arbitrarily pick the first one.
2295 return query.get(0);
2296 }
2297 }
2298 return null;
2299 }
2300
2301 public List<ResolveInfo> queryIntentServices(Intent intent,
2302 String resolvedType, int flags) {
2303 ComponentName comp = intent.getComponent();
2304 if (comp != null) {
2305 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2306 ServiceInfo si = getServiceInfo(comp, flags);
2307 if (si != null) {
2308 ResolveInfo ri = new ResolveInfo();
2309 ri.serviceInfo = si;
2310 list.add(ri);
2311 }
2312 return list;
2313 }
2314
2315 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002316 String pkgName = intent.getPackage();
2317 if (pkgName == null) {
Jason parks1125d782011-01-12 09:47:26 -06002318 return mServices.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002319 resolvedType, flags);
2320 }
2321 PackageParser.Package pkg = mPackages.get(pkgName);
2322 if (pkg != null) {
Jason parks1125d782011-01-12 09:47:26 -06002323 return mServices.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002324 resolvedType, flags, pkg.services);
2325 }
2326 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 }
2328 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002330 public List<PackageInfo> getInstalledPackages(int flags) {
2331 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2332
2333 synchronized (mPackages) {
2334 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2335 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2336 while (i.hasNext()) {
2337 final PackageSetting ps = i.next();
2338 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2339 if(psPkg != null) {
2340 finalList.add(psPkg);
2341 }
2342 }
2343 }
2344 else {
2345 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2346 while (i.hasNext()) {
2347 final PackageParser.Package p = i.next();
2348 if (p.applicationInfo != null) {
2349 PackageInfo pi = generatePackageInfo(p, flags);
2350 if(pi != null) {
2351 finalList.add(pi);
2352 }
2353 }
2354 }
2355 }
2356 }
2357 return finalList;
2358 }
2359
2360 public List<ApplicationInfo> getInstalledApplications(int flags) {
2361 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2362 synchronized(mPackages) {
2363 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2364 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2365 while (i.hasNext()) {
2366 final PackageSetting ps = i.next();
2367 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2368 if(ai != null) {
2369 finalList.add(ai);
2370 }
2371 }
2372 }
2373 else {
2374 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2375 while (i.hasNext()) {
2376 final PackageParser.Package p = i.next();
2377 if (p.applicationInfo != null) {
2378 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2379 if(ai != null) {
2380 finalList.add(ai);
2381 }
2382 }
2383 }
2384 }
2385 }
2386 return finalList;
2387 }
2388
2389 public List<ApplicationInfo> getPersistentApplications(int flags) {
2390 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2391
2392 synchronized (mPackages) {
2393 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2394 while (i.hasNext()) {
2395 PackageParser.Package p = i.next();
2396 if (p.applicationInfo != null
2397 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002398 && (!mSafeMode || isSystemApp(p))) {
Jey2eebf5c2009-11-18 18:37:31 -08002399 finalList.add(PackageParser.generateApplicationInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 }
2401 }
2402 }
2403
2404 return finalList;
2405 }
2406
2407 public ProviderInfo resolveContentProvider(String name, int flags) {
2408 synchronized (mPackages) {
2409 final PackageParser.Provider provider = mProviders.get(name);
2410 return provider != null
2411 && mSettings.isEnabledLP(provider.info, flags)
2412 && (!mSafeMode || (provider.info.applicationInfo.flags
2413 &ApplicationInfo.FLAG_SYSTEM) != 0)
2414 ? PackageParser.generateProviderInfo(provider, flags)
2415 : null;
2416 }
2417 }
2418
Fred Quintana718d8a22009-04-29 17:53:20 -07002419 /**
2420 * @deprecated
2421 */
Jason parks1125d782011-01-12 09:47:26 -06002422 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002423 public void querySyncProviders(List outNames, List outInfo) {
2424 synchronized (mPackages) {
2425 Iterator<Map.Entry<String, PackageParser.Provider>> i
2426 = mProviders.entrySet().iterator();
2427
2428 while (i.hasNext()) {
2429 Map.Entry<String, PackageParser.Provider> entry = i.next();
2430 PackageParser.Provider p = entry.getValue();
2431
2432 if (p.syncable
2433 && (!mSafeMode || (p.info.applicationInfo.flags
2434 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2435 outNames.add(entry.getKey());
2436 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2437 }
2438 }
2439 }
2440 }
2441
2442 public List<ProviderInfo> queryContentProviders(String processName,
2443 int uid, int flags) {
2444 ArrayList<ProviderInfo> finalList = null;
2445
2446 synchronized (mPackages) {
2447 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2448 while (i.hasNext()) {
2449 PackageParser.Provider p = i.next();
2450 if (p.info.authority != null
2451 && (processName == null ||
2452 (p.info.processName.equals(processName)
2453 && p.info.applicationInfo.uid == uid))
2454 && mSettings.isEnabledLP(p.info, flags)
2455 && (!mSafeMode || (p.info.applicationInfo.flags
2456 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2457 if (finalList == null) {
2458 finalList = new ArrayList<ProviderInfo>(3);
2459 }
2460 finalList.add(PackageParser.generateProviderInfo(p,
2461 flags));
2462 }
2463 }
2464 }
2465
2466 if (finalList != null) {
2467 Collections.sort(finalList, mProviderInitOrderSorter);
2468 }
2469
2470 return finalList;
2471 }
2472
2473 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2474 int flags) {
2475 synchronized (mPackages) {
2476 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2477 return PackageParser.generateInstrumentationInfo(i, flags);
2478 }
2479 }
2480
2481 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2482 int flags) {
2483 ArrayList<InstrumentationInfo> finalList =
2484 new ArrayList<InstrumentationInfo>();
2485
2486 synchronized (mPackages) {
2487 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2488 while (i.hasNext()) {
2489 PackageParser.Instrumentation p = i.next();
2490 if (targetPackage == null
2491 || targetPackage.equals(p.info.targetPackage)) {
2492 finalList.add(PackageParser.generateInstrumentationInfo(p,
2493 flags));
2494 }
2495 }
2496 }
2497
2498 return finalList;
2499 }
2500
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002501 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07002503 if (files == null) {
2504 Log.d(TAG, "No files in app dir " + dir);
2505 return;
2506 }
2507
Joe Onorato431bb222010-10-18 19:13:23 -04002508 if (false) {
2509 Log.d(TAG, "Scanning app dir " + dir);
2510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511
2512 int i;
2513 for (i=0; i<files.length; i++) {
2514 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002515 if (!isPackageFilename(files[i])) {
2516 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002517 continue;
2518 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002519 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002520 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002521 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002522 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2523 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002524 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002525 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002526 file.delete();
2527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 }
2529 }
2530
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002531 private static File getSettingsProblemFile() {
2532 File dataDir = Environment.getDataDirectory();
2533 File systemDir = new File(dataDir, "system");
2534 File fname = new File(systemDir, "uiderrors.txt");
2535 return fname;
2536 }
2537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002538 private static void reportSettingsProblem(int priority, String msg) {
2539 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002540 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 FileOutputStream out = new FileOutputStream(fname, true);
2542 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002543 SimpleDateFormat formatter = new SimpleDateFormat();
2544 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2545 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 pw.close();
2547 FileUtils.setPermissions(
2548 fname.toString(),
2549 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2550 -1, -1);
2551 } catch (java.io.IOException e) {
2552 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002553 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 }
2555
2556 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2557 PackageParser.Package pkg, File srcFile, int parseFlags) {
2558 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07002559 if (ps != null
2560 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07002561 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07002562 if (ps.signatures.mSignatures != null
2563 && ps.signatures.mSignatures.length != 0) {
2564 // Optimization: reuse the existing cached certificates
2565 // if the package appears to be unchanged.
2566 pkg.mSignatures = ps.signatures.mSignatures;
2567 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 }
Jeff Browne7600722010-04-07 18:28:23 -07002569
2570 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002571 } else {
Jeff Browne7600722010-04-07 18:28:23 -07002572 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2573 }
2574
2575 if (!pp.collectCertificates(pkg, parseFlags)) {
2576 mLastScanError = pp.getParseError();
2577 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 }
2579 }
2580 return true;
2581 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 /*
2584 * Scan a package and return the newly parsed package.
2585 * Returns null in case of errors and the error code is stored in mLastScanError
2586 */
2587 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002588 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002590 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002592 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002595 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 if (pkg == null) {
2597 mLastScanError = pp.getParseError();
2598 return null;
2599 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002600 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 PackageSetting updatedPkg;
2602 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002603 // Look to see if we already know about this package.
2604 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002605 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002606 // This package has been renamed to its original name. Let's
2607 // use that.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002608 ps = mSettings.peekPackageLP(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002609 }
2610 // If there was no original package, see one for the real package name.
2611 if (ps == null) {
2612 ps = mSettings.peekPackageLP(pkg.packageName);
2613 }
2614 // Check to see if this package could be hiding/updating a system
2615 // package. Must look for it either under the original or real
2616 // package name depending on our state.
2617 updatedPkg = mSettings.mDisabledSysPackages.get(
2618 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002620 // First check if this is a system package that may involve an update
2621 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07002622 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002623 // The path has changed from what was last scanned... check the
2624 // version of the new path against what we have stored to determine
2625 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002626 if (pkg.mVersionCode < ps.versionCode) {
2627 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002628 // Ignore entry. Skip it.
2629 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002630 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002631 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002632 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2633 return null;
2634 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002635 // The current app on the system partion is better than
2636 // what we have updated to on the data partition; switch
2637 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002638 // At this point, its safely assumed that package installation for
2639 // apps in system partition will go through. If not there won't be a working
2640 // version of the app
2641 synchronized (mPackages) {
2642 // Just remove the loaded entries from package lists.
2643 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002644 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002645 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002646 + "reverting from " + ps.codePathString
2647 + ": new version " + pkg.mVersionCode
2648 + " better than installed " + ps.versionCode);
Kenny Root85387d72010-08-26 10:13:11 -07002649 InstallArgs args = new FileInstallArgs(ps.codePathString,
2650 ps.resourcePathString, ps.nativeLibraryPathString);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002651 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002652 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 }
2655 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002656 if (updatedPkg != null) {
2657 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2658 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2659 }
2660 // Verify certificates against what was last scanned
2661 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002662 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002663 return null;
2664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 // The apk is forward locked (not public) if its code and resources
2666 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002667 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002669 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002670 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002671
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002672 String codePath = null;
2673 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002674 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2675 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002676 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002677 } else {
2678 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002679 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002680 }
2681 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002682 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002683 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002684 codePath = pkg.mScanPath;
2685 // Set application objects path explicitly.
2686 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 // Note that we invoke the following method only if we are about to unpack an application
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002688 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 }
2690
Kenny Root85387d72010-08-26 10:13:11 -07002691 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
2692 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002693 pkg.mPath = pkg.mScanPath = destCodePath;
2694 pkg.applicationInfo.sourceDir = destCodePath;
2695 pkg.applicationInfo.publicSourceDir = destResPath;
2696 }
2697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 private static String fixProcessName(String defProcessName,
2699 String processName, int uid) {
2700 if (processName == null) {
2701 return defProcessName;
2702 }
2703 return processName;
2704 }
2705
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002706 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002707 PackageParser.Package pkg) {
2708 if (pkgSetting.signatures.mSignatures != null) {
2709 // Already existing package. Make sure signatures match
2710 if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
2711 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002712 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002713 + " signatures do not match the previously installed version; ignoring!");
2714 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 return false;
2716 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002717 }
2718 // Check for shared user signatures
2719 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
2720 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
2721 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
2722 Slog.e(TAG, "Package " + pkg.packageName
2723 + " has no signatures that match those in shared user "
2724 + pkgSetting.sharedUser.name + "; ignoring!");
2725 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2726 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 }
2729 return true;
2730 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002731
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002732 public boolean performDexOpt(String packageName) {
2733 if (!mNoDexOpt) {
2734 return false;
2735 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002736
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002737 PackageParser.Package p;
2738 synchronized (mPackages) {
2739 p = mPackages.get(packageName);
2740 if (p == null || p.mDidDexOpt) {
2741 return false;
2742 }
2743 }
2744 synchronized (mInstallLock) {
2745 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2746 }
2747 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002748
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002749 static final int DEX_OPT_SKIPPED = 0;
2750 static final int DEX_OPT_PERFORMED = 1;
2751 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002752
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002753 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2754 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002755 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002756 String path = pkg.mScanPath;
2757 int ret = 0;
2758 try {
2759 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002760 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002761 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002762 pkg.mDidDexOpt = true;
2763 performed = true;
2764 }
2765 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002766 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002767 ret = -1;
2768 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07002769 Slog.w(TAG, "IOException reading apk: " + path, e);
2770 ret = -1;
2771 } catch (dalvik.system.StaleDexCacheError e) {
2772 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
2773 ret = -1;
2774 } catch (Exception e) {
2775 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002776 ret = -1;
2777 }
2778 if (ret < 0) {
2779 //error from installer
2780 return DEX_OPT_FAILED;
2781 }
2782 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002783
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002784 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2785 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002786
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002787 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2788 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002789 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002790 + " to " + newPkg.packageName
2791 + ": old package not in system partition");
2792 return false;
2793 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002794 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002795 + " to " + newPkg.packageName
2796 + ": old package still exists");
2797 return false;
2798 }
2799 return true;
2800 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002801
2802 private File getDataPathForPackage(PackageParser.Package pkg) {
Jason parks1125d782011-01-12 09:47:26 -06002803 return new File(mAppDataDir, pkg.packageName);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002804 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002805
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002806 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002807 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002808 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002809 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2810 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002811 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002812 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002813 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2814 return null;
2815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 mScanningPath = scanFile;
2817 if (pkg == null) {
2818 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2819 return null;
2820 }
2821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2823 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2824 }
2825
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002826 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827 synchronized (mPackages) {
2828 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002829 Slog.w(TAG, "*************************************************");
2830 Slog.w(TAG, "Core android package being redefined. Skipping.");
2831 Slog.w(TAG, " file=" + mScanningPath);
2832 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2834 return null;
2835 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 // Set up information for our fall-back user intent resolution
2838 // activity.
2839 mPlatformPackage = pkg;
2840 pkg.mVersionCode = mSdkVersion;
2841 mAndroidApplication = pkg.applicationInfo;
2842 mResolveActivity.applicationInfo = mAndroidApplication;
2843 mResolveActivity.name = ResolverActivity.class.getName();
2844 mResolveActivity.packageName = mAndroidApplication.packageName;
2845 mResolveActivity.processName = mAndroidApplication.processName;
2846 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2847 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08002848 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849 mResolveActivity.exported = true;
2850 mResolveActivity.enabled = true;
2851 mResolveInfo.activityInfo = mResolveActivity;
2852 mResolveInfo.priority = 0;
2853 mResolveInfo.preferredOrder = 0;
2854 mResolveInfo.match = 0;
2855 mResolveComponentName = new ComponentName(
2856 mAndroidApplication.packageName, mResolveActivity.name);
2857 }
2858 }
2859
2860 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002861 TAG, "Scanning package " + pkg.packageName);
2862 if (mPackages.containsKey(pkg.packageName)
2863 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002864 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2867 return null;
2868 }
2869
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002870 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002871 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2872 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 SharedUserSetting suid = null;
2875 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002876
Kenny Root502e9a42011-01-10 13:48:15 -08002877 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002878 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002879 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002880 pkg.mRealPackage = null;
2881 pkg.mAdoptPermissions = null;
2882 }
Kenny Root502e9a42011-01-10 13:48:15 -08002883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 synchronized (mPackages) {
2885 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002886 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2887 if (mTmpSharedLibraries == null ||
2888 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2889 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2890 }
2891 int num = 0;
2892 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2893 for (int i=0; i<N; i++) {
2894 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002896 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002898 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2900 return null;
2901 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002902 mTmpSharedLibraries[num] = file;
2903 num++;
2904 }
2905 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2906 for (int i=0; i<N; i++) {
2907 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2908 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002909 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07002910 + " desires unavailable shared library "
2911 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2912 } else {
2913 mTmpSharedLibraries[num] = file;
2914 num++;
2915 }
2916 }
2917 if (num > 0) {
2918 pkg.usesLibraryFiles = new String[num];
2919 System.arraycopy(mTmpSharedLibraries, 0,
2920 pkg.usesLibraryFiles, 0, num);
2921 }
Kenny Root1683afa2011-01-07 14:27:50 -08002922 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002923
Kenny Root1683afa2011-01-07 14:27:50 -08002924 if (pkg.reqFeatures != null) {
2925 int N = pkg.reqFeatures.size();
2926 for (int i = 0; i < N; i++) {
2927 FeatureInfo fi = pkg.reqFeatures.get(i);
2928 if ((fi.flags & FeatureInfo.FLAG_REQUIRED) == 0) {
2929 // Don't care.
2930 continue;
2931 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002932
Kenny Root1683afa2011-01-07 14:27:50 -08002933 if (fi.name != null) {
2934 if (mAvailableFeatures.get(fi.name) == null) {
2935 Slog.e(TAG, "Package " + pkg.packageName
2936 + " requires unavailable feature " + fi.name + "; failing!");
2937 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2938 return null;
Dianne Hackborn49237342009-08-27 20:08:01 -07002939 }
2940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 }
2942 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 if (pkg.mSharedUserId != null) {
2945 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2946 pkg.applicationInfo.flags, true);
2947 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002948 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 + " for shared user failed");
2950 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2951 return null;
2952 }
2953 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2954 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2955 + suid.userId + "): packages=" + suid.packages);
2956 }
2957 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002958
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002959 if (false) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002960 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002961 Log.w(TAG, "WAITING FOR DEBUGGER");
2962 Debug.waitForDebugger();
Dianne Hackbornc1552392010-03-03 16:19:01 -08002963 Log.i(TAG, "Package " + pkg.packageName + " from original packages"
2964 + pkg.mOriginalPackages);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002965 }
2966 }
2967
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002968 // Check if we are renaming from an original package name.
2969 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002970 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08002971 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002972 // This package may need to be renamed to a previously
2973 // installed name. Let's check on that...
2974 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002975 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002976 // This package had originally been installed as the
2977 // original name, and we have already taken care of
2978 // transitioning to the new one. Just update the new
2979 // one to continue using the old name.
2980 realName = pkg.mRealPackage;
2981 if (!pkg.packageName.equals(renamed)) {
2982 // Callers into this function may have already taken
2983 // care of renaming the package; only do it here if
2984 // it is not already done.
2985 pkg.setPackageName(renamed);
2986 }
2987
Dianne Hackbornc1552392010-03-03 16:19:01 -08002988 } else {
2989 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
2990 if ((origPackage=mSettings.peekPackageLP(
2991 pkg.mOriginalPackages.get(i))) != null) {
2992 // We do have the package already installed under its
2993 // original name... should we use it?
2994 if (!verifyPackageUpdate(origPackage, pkg)) {
2995 // New package is not compatible with original.
2996 origPackage = null;
2997 continue;
2998 } else if (origPackage.sharedUser != null) {
2999 // Make sure uid is compatible between packages.
3000 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003001 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08003002 + " to " + pkg.packageName + ": old uid "
3003 + origPackage.sharedUser.name
3004 + " differs from " + pkg.mSharedUserId);
3005 origPackage = null;
3006 continue;
3007 }
3008 } else {
3009 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
3010 + pkg.packageName + " to old name " + origPackage.name);
3011 }
3012 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003013 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003014 }
3015 }
3016 }
3017
3018 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003019 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003020 + " was transferred to another, but its .apk remains");
3021 }
3022
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003023 // Just create the setting, don't add it yet. For already existing packages
3024 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003025 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003026 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3027 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003029 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3031 return null;
3032 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003033
3034 if (pkgSetting.origPackage != null) {
3035 // If we are first transitioning from an original package,
3036 // fix up the new package's name now. We need to do this after
3037 // looking up the package under its new name, so getPackageLP
3038 // can take care of fiddling things correctly.
3039 pkg.setPackageName(origPackage.name);
3040
3041 // File a report about this.
3042 String msg = "New package " + pkgSetting.realName
3043 + " renamed to replace old package " + pkgSetting.name;
3044 reportSettingsProblem(Log.WARN, msg);
3045
3046 // Make a note of it.
3047 mTransferedPackages.add(origPackage.name);
3048
3049 // No longer need to retain this.
3050 pkgSetting.origPackage = null;
3051 }
3052
3053 if (realName != null) {
3054 // Make a note of it.
3055 mTransferedPackages.add(pkg.packageName);
3056 }
3057
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003058 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3060 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 pkg.applicationInfo.uid = pkgSetting.userId;
3063 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003064
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003065 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003066 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 return null;
3068 }
3069 // The signature has changed, but this package is in the system
3070 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003071 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 // However... if this package is part of a shared user, but it
3073 // doesn't match the signature of the shared user, let's fail.
3074 // What this means is that you can't change the signatures
3075 // associated with an overall shared user, which doesn't seem all
3076 // that unreasonable.
3077 if (pkgSetting.sharedUser != null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003078 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
3079 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3080 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3082 return null;
3083 }
3084 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003085 // File a report about this.
3086 String msg = "System package " + pkg.packageName
3087 + " signature changed; retaining data.";
3088 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003090
The Android Open Source Project10592532009-03-18 17:39:46 -07003091 // Verify that this new package doesn't have any content providers
3092 // that conflict with existing packages. Only do this if the
3093 // package isn't already installed, since we don't want to break
3094 // things that are installed.
3095 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
3096 int N = pkg.providers.size();
3097 int i;
3098 for (i=0; i<N; i++) {
3099 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003100 if (p.info.authority != null) {
3101 String names[] = p.info.authority.split(";");
3102 for (int j = 0; j < names.length; j++) {
3103 if (mProviders.containsKey(names[j])) {
3104 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003105 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003106 " (in package " + pkg.applicationInfo.packageName +
3107 ") is already used by "
3108 + ((other != null && other.getComponentName() != null)
3109 ? other.getComponentName().getPackageName() : "?"));
3110 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3111 return null;
3112 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003113 }
3114 }
3115 }
3116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 }
3118
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003119 final String pkgName = pkg.packageName;
3120
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003121 if (pkg.mAdoptPermissions != null) {
3122 // This package wants to adopt ownership of permissions from
3123 // another package.
3124 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
3125 String origName = pkg.mAdoptPermissions.get(i);
3126 PackageSetting orig = mSettings.peekPackageLP(origName);
3127 if (orig != null) {
3128 if (verifyPackageUpdate(orig, pkg)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003129 Slog.i(TAG, "Adopting permissions from "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003130 + origName + " to " + pkg.packageName);
3131 mSettings.transferPermissions(origName, pkg.packageName);
3132 }
3133 }
3134 }
3135 }
3136
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003137 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003138 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
Kenny Root7d794fb2010-09-13 16:29:49 -07003139 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.timeStamp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 pkg.applicationInfo.processName = fixProcessName(
3141 pkg.applicationInfo.packageName,
3142 pkg.applicationInfo.processName,
3143 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144
3145 File dataPath;
3146 if (mPlatformPackage == pkg) {
3147 // The system package is special.
3148 dataPath = new File (Environment.getDataDirectory(), "system");
3149 pkg.applicationInfo.dataDir = dataPath.getPath();
3150 } else {
3151 // This is a normal package, need to make its data directory.
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003152 dataPath = getDataPathForPackage(pkg);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003153
3154 boolean uidError = false;
3155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 if (dataPath.exists()) {
3157 mOutPermissions[1] = 0;
3158 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003159
3160 // If we have mismatched owners for the data path, we have a
3161 // problem (unless we're running in the simulator.)
3162 if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 boolean recovered = false;
3164 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3165 // If this is a system app, we can at least delete its
3166 // current data so the application will still work.
3167 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06003168 int ret = mInstaller.remove(pkgName);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003169 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 // Old data gone!
3171 String msg = "System package " + pkg.packageName
3172 + " has changed from uid: "
3173 + mOutPermissions[1] + " to "
3174 + pkg.applicationInfo.uid + "; old data erased";
3175 reportSettingsProblem(Log.WARN, msg);
3176 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 // And now re-install the app.
Jason parks1125d782011-01-12 09:47:26 -06003179 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 pkg.applicationInfo.uid);
3181 if (ret == -1) {
3182 // Ack should not happen!
3183 msg = "System package " + pkg.packageName
3184 + " could not have data directory re-created after delete.";
3185 reportSettingsProblem(Log.WARN, msg);
3186 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3187 return null;
3188 }
3189 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003190 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 if (!recovered) {
3192 mHasSystemUidErrors = true;
3193 }
3194 }
3195 if (!recovered) {
3196 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3197 + pkg.applicationInfo.uid + "/fs_"
3198 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003199 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 String msg = "Package " + pkg.packageName
3201 + " has mismatched uid: "
3202 + mOutPermissions[1] + " on disk, "
3203 + pkg.applicationInfo.uid + " in settings";
3204 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003205 mSettings.mReadMessages.append(msg);
3206 mSettings.mReadMessages.append('\n');
3207 uidError = true;
3208 if (!pkgSetting.uidError) {
3209 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003211 }
3212 }
3213 }
3214 pkg.applicationInfo.dataDir = dataPath.getPath();
3215 } else {
3216 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
3217 Log.v(TAG, "Want this data dir: " + dataPath);
3218 //invoke installer to do the actual installation
3219 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06003220 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 pkg.applicationInfo.uid);
3222 if(ret < 0) {
3223 // Error from installer
3224 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3225 return null;
3226 }
3227 } else {
3228 dataPath.mkdirs();
3229 if (dataPath.exists()) {
3230 FileUtils.setPermissions(
3231 dataPath.toString(),
3232 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3233 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
3234 }
3235 }
3236 if (dataPath.exists()) {
3237 pkg.applicationInfo.dataDir = dataPath.getPath();
3238 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003239 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 pkg.applicationInfo.dataDir = null;
3241 }
3242 }
Kenny Root85387d72010-08-26 10:13:11 -07003243
3244 /*
3245 * Set the data dir to the default "/data/data/<package name>/lib"
3246 * if we got here without anyone telling us different (e.g., apps
3247 * stored on SD card have their native libraries stored in the ASEC
3248 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003249 *
3250 * This happens during an upgrade from a package settings file that
3251 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003252 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003253 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3254 if (pkgSetting.nativeLibraryPathString == null) {
3255 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3256 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3257 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3258 } else {
3259 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3260 }
Kenny Root85387d72010-08-26 10:13:11 -07003261 }
3262
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003263 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003264 }
3265
Kenny Root85387d72010-08-26 10:13:11 -07003266 // If we're running in the simulator, we don't need to unpack anything.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003267 if (mInstaller != null) {
3268 String path = scanFile.getPath();
Kenny Root85387d72010-08-26 10:13:11 -07003269 /* Note: We don't want to unpack the native binaries for
3270 * system applications, unless they have been updated
3271 * (the binaries are already under /system/lib).
3272 * Also, don't unpack libs for apps on the external card
3273 * since they should have their libraries in the ASEC
3274 * container already.
3275 *
3276 * In other words, we're going to unpack the binaries
3277 * only for non-system apps and system app upgrades.
3278 */
Kenny Root831baa22010-10-05 12:29:25 -07003279 if (pkg.applicationInfo.nativeLibraryDir != null) {
Kenny Roote68d58a2010-10-18 16:08:54 -07003280 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
3281 final String dataPathString = dataPath.getPath();
3282
Kenny Root831baa22010-10-05 12:29:25 -07003283 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3284 /*
3285 * Upgrading from a previous version of the OS sometimes
3286 * leaves native libraries in the /data/data/<app>/lib
3287 * directory for system apps even when they shouldn't be.
3288 * Recent changes in the JNI library search path
3289 * necessitates we remove those to match previous behavior.
3290 */
Kenny Roote68d58a2010-10-18 16:08:54 -07003291 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
Kenny Root831baa22010-10-05 12:29:25 -07003292 Log.i(TAG, "removed obsolete native libraries for system package " + path);
3293 }
Kenny Roote68d58a2010-10-18 16:08:54 -07003294 } else if (nativeLibraryDir.getParent().equals(dataPathString)) {
3295 /*
3296 * If this is an internal application or our
3297 * nativeLibraryPath points to our data directory, unpack
3298 * the libraries. The native library path pointing to the
3299 * data directory for an application in an ASEC container
3300 * can happen for older apps that existed before an OTA to
3301 * Gingerbread.
3302 */
3303 Slog.i(TAG, "Unpacking native libraries for " + path);
3304 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3305 NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
Kenny Root6a6b0072010-10-07 16:46:10 -07003306 } else {
Kenny Roote68d58a2010-10-18 16:08:54 -07003307 Slog.i(TAG, "Linking native library dir for " + path);
3308 mInstaller.linkNativeLibraryDirectory(dataPathString,
Kenny Root6a6b0072010-10-07 16:46:10 -07003309 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003312 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003313
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003314 if ((scanMode&SCAN_NO_DEX) == 0) {
3315 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3317 return null;
3318 }
3319 }
3320 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 if (mFactoryTest && pkg.requestedPermissions.contains(
3323 android.Manifest.permission.FACTORY_TEST)) {
3324 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3325 }
3326
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003327 // Request the ActivityManager to kill the process(only for existing packages)
3328 // so that we do not end up in a confused state while the user is still using the older
3329 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003330 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003331 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003332 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003333 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003335 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003336 // We don't expect installation to fail beyond this point,
3337 if ((scanMode&SCAN_MONITOR) != 0) {
3338 mAppDirs.put(pkg.mPath, pkg);
3339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003341 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003342 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003343 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003344 // Make sure we don't accidentally delete its data.
3345 mSettings.mPackagesToBeCleaned.remove(pkgName);
3346
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003347 // Take care of first install / last update times.
3348 if (currentTime != 0) {
3349 if (pkgSetting.firstInstallTime == 0) {
3350 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
3351 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
3352 pkgSetting.lastUpdateTime = currentTime;
3353 }
3354 } else if (pkgSetting.firstInstallTime == 0) {
3355 // We need *something*. Take time time stamp of the file.
3356 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
3357 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
3358 if (scanFileTime != pkgSetting.timeStamp) {
3359 // A package on the system image has changed; consider this
3360 // to be an update.
3361 pkgSetting.lastUpdateTime = scanFileTime;
3362 }
3363 }
3364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 int N = pkg.providers.size();
3366 StringBuilder r = null;
3367 int i;
3368 for (i=0; i<N; i++) {
3369 PackageParser.Provider p = pkg.providers.get(i);
3370 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3371 p.info.processName, pkg.applicationInfo.uid);
3372 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3373 p.info.name), p);
3374 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003375 if (p.info.authority != null) {
3376 String names[] = p.info.authority.split(";");
3377 p.info.authority = null;
3378 for (int j = 0; j < names.length; j++) {
3379 if (j == 1 && p.syncable) {
3380 // We only want the first authority for a provider to possibly be
3381 // syncable, so if we already added this provider using a different
3382 // authority clear the syncable flag. We copy the provider before
3383 // changing it because the mProviders object contains a reference
3384 // to a provider that we don't want to change.
3385 // Only do this for the second authority since the resulting provider
3386 // object can be the same for all future authorities for this provider.
3387 p = new PackageParser.Provider(p);
3388 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003390 if (!mProviders.containsKey(names[j])) {
3391 mProviders.put(names[j], p);
3392 if (p.info.authority == null) {
3393 p.info.authority = names[j];
3394 } else {
3395 p.info.authority = p.info.authority + ";" + names[j];
3396 }
3397 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
3398 Log.d(TAG, "Registered content provider: " + names[j] +
3399 ", className = " + p.info.name +
3400 ", isSyncable = " + p.info.isSyncable);
3401 } else {
3402 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003403 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003404 " (in package " + pkg.applicationInfo.packageName +
3405 "): name already used by "
3406 + ((other != null && other.getComponentName() != null)
3407 ? other.getComponentName().getPackageName() : "?"));
3408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 }
3410 }
3411 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3412 if (r == null) {
3413 r = new StringBuilder(256);
3414 } else {
3415 r.append(' ');
3416 }
3417 r.append(p.info.name);
3418 }
3419 }
3420 if (r != null) {
3421 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3422 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 N = pkg.services.size();
3425 r = null;
3426 for (i=0; i<N; i++) {
3427 PackageParser.Service s = pkg.services.get(i);
3428 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3429 s.info.processName, pkg.applicationInfo.uid);
3430 mServices.addService(s);
3431 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3432 if (r == null) {
3433 r = new StringBuilder(256);
3434 } else {
3435 r.append(' ');
3436 }
3437 r.append(s.info.name);
3438 }
3439 }
3440 if (r != null) {
3441 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3442 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003444 N = pkg.receivers.size();
3445 r = null;
3446 for (i=0; i<N; i++) {
3447 PackageParser.Activity a = pkg.receivers.get(i);
3448 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3449 a.info.processName, pkg.applicationInfo.uid);
3450 mReceivers.addActivity(a, "receiver");
3451 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3452 if (r == null) {
3453 r = new StringBuilder(256);
3454 } else {
3455 r.append(' ');
3456 }
3457 r.append(a.info.name);
3458 }
3459 }
3460 if (r != null) {
3461 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3462 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 N = pkg.activities.size();
3465 r = null;
3466 for (i=0; i<N; i++) {
3467 PackageParser.Activity a = pkg.activities.get(i);
3468 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3469 a.info.processName, pkg.applicationInfo.uid);
3470 mActivities.addActivity(a, "activity");
3471 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3472 if (r == null) {
3473 r = new StringBuilder(256);
3474 } else {
3475 r.append(' ');
3476 }
3477 r.append(a.info.name);
3478 }
3479 }
3480 if (r != null) {
3481 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3482 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 N = pkg.permissionGroups.size();
3485 r = null;
3486 for (i=0; i<N; i++) {
3487 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3488 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3489 if (cur == null) {
3490 mPermissionGroups.put(pg.info.name, pg);
3491 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3492 if (r == null) {
3493 r = new StringBuilder(256);
3494 } else {
3495 r.append(' ');
3496 }
3497 r.append(pg.info.name);
3498 }
3499 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003500 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003501 + pg.info.packageName + " ignored: original from "
3502 + cur.info.packageName);
3503 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3504 if (r == null) {
3505 r = new StringBuilder(256);
3506 } else {
3507 r.append(' ');
3508 }
3509 r.append("DUP:");
3510 r.append(pg.info.name);
3511 }
3512 }
3513 }
3514 if (r != null) {
3515 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3516 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 N = pkg.permissions.size();
3519 r = null;
3520 for (i=0; i<N; i++) {
3521 PackageParser.Permission p = pkg.permissions.get(i);
3522 HashMap<String, BasePermission> permissionMap =
3523 p.tree ? mSettings.mPermissionTrees
3524 : mSettings.mPermissions;
3525 p.group = mPermissionGroups.get(p.info.group);
3526 if (p.info.group == null || p.group != null) {
3527 BasePermission bp = permissionMap.get(p.info.name);
3528 if (bp == null) {
3529 bp = new BasePermission(p.info.name, p.info.packageName,
3530 BasePermission.TYPE_NORMAL);
3531 permissionMap.put(p.info.name, bp);
3532 }
3533 if (bp.perm == null) {
3534 if (bp.sourcePackage == null
3535 || bp.sourcePackage.equals(p.info.packageName)) {
3536 BasePermission tree = findPermissionTreeLP(p.info.name);
3537 if (tree == null
3538 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003539 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 bp.perm = p;
3541 bp.uid = pkg.applicationInfo.uid;
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(p.info.name);
3549 }
3550 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003551 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 + p.info.packageName + " ignored: base tree "
3553 + tree.name + " is from package "
3554 + tree.sourcePackage);
3555 }
3556 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003557 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 + p.info.packageName + " ignored: original from "
3559 + bp.sourcePackage);
3560 }
3561 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3562 if (r == null) {
3563 r = new StringBuilder(256);
3564 } else {
3565 r.append(' ');
3566 }
3567 r.append("DUP:");
3568 r.append(p.info.name);
3569 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003570 if (bp.perm == p) {
3571 bp.protectionLevel = p.info.protectionLevel;
3572 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003574 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 + p.info.packageName + " ignored: no group "
3576 + p.group);
3577 }
3578 }
3579 if (r != null) {
3580 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3581 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 N = pkg.instrumentation.size();
3584 r = null;
3585 for (i=0; i<N; i++) {
3586 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3587 a.info.packageName = pkg.applicationInfo.packageName;
3588 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3589 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3590 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07003591 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003592 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3594 if (r == null) {
3595 r = new StringBuilder(256);
3596 } else {
3597 r.append(' ');
3598 }
3599 r.append(a.info.name);
3600 }
3601 }
3602 if (r != null) {
3603 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3604 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003605
Dianne Hackborn854060af2009-07-09 18:14:31 -07003606 if (pkg.protectedBroadcasts != null) {
3607 N = pkg.protectedBroadcasts.size();
3608 for (i=0; i<N; i++) {
3609 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3610 }
3611 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 pkgSetting.setTimeStamp(scanFileTime);
3614 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 return pkg;
3617 }
3618
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003619 private void killApplication(String pkgName, int uid) {
3620 // Request the ActivityManager to kill the process(only for existing packages)
3621 // so that we do not end up in a confused state while the user is still using the older
3622 // version of the application while the new one gets installed.
3623 IActivityManager am = ActivityManagerNative.getDefault();
3624 if (am != null) {
3625 try {
3626 am.killApplicationWithUid(pkgName, uid);
3627 } catch (RemoteException e) {
3628 }
3629 }
3630 }
3631
David 'Digit' Turner4f99e3c2010-04-12 16:11:15 -07003632 // Return the path of the directory that will contain the native binaries
3633 // of a given installed package. This is relative to the data path.
3634 //
Kenny Root85387d72010-08-26 10:13:11 -07003635 private File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
3636 final String nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
3637 if (nativeLibraryDir != null) {
3638 return new File(nativeLibraryDir);
3639 } else {
3640 // Fall back for old packages
3641 return new File(pkg.applicationInfo.dataDir, LIB_DIR_NAME);
3642 }
David 'Digit' Turner4f99e3c2010-04-12 16:11:15 -07003643 }
3644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3646 if (chatty && Config.LOGD) Log.d(
3647 TAG, "Removing package " + pkg.applicationInfo.packageName );
3648
3649 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003652 mPackages.remove(pkg.applicationInfo.packageName);
3653 if (pkg.mPath != null) {
3654 mAppDirs.remove(pkg.mPath);
3655 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 int N = pkg.providers.size();
3658 StringBuilder r = null;
3659 int i;
3660 for (i=0; i<N; i++) {
3661 PackageParser.Provider p = pkg.providers.get(i);
3662 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3663 p.info.name));
3664 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 /* The is another ContentProvider with this authority when
3667 * this app was installed so this authority is null,
3668 * Ignore it as we don't have to unregister the provider.
3669 */
3670 continue;
3671 }
3672 String names[] = p.info.authority.split(";");
3673 for (int j = 0; j < names.length; j++) {
3674 if (mProviders.get(names[j]) == p) {
3675 mProviders.remove(names[j]);
3676 if (chatty && Config.LOGD) Log.d(
3677 TAG, "Unregistered content provider: " + names[j] +
3678 ", className = " + p.info.name +
3679 ", isSyncable = " + p.info.isSyncable);
3680 }
3681 }
3682 if (chatty) {
3683 if (r == null) {
3684 r = new StringBuilder(256);
3685 } else {
3686 r.append(' ');
3687 }
3688 r.append(p.info.name);
3689 }
3690 }
3691 if (r != null) {
3692 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3693 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 N = pkg.services.size();
3696 r = null;
3697 for (i=0; i<N; i++) {
3698 PackageParser.Service s = pkg.services.get(i);
3699 mServices.removeService(s);
3700 if (chatty) {
3701 if (r == null) {
3702 r = new StringBuilder(256);
3703 } else {
3704 r.append(' ');
3705 }
3706 r.append(s.info.name);
3707 }
3708 }
3709 if (r != null) {
3710 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3711 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 N = pkg.receivers.size();
3714 r = null;
3715 for (i=0; i<N; i++) {
3716 PackageParser.Activity a = pkg.receivers.get(i);
3717 mReceivers.removeActivity(a, "receiver");
3718 if (chatty) {
3719 if (r == null) {
3720 r = new StringBuilder(256);
3721 } else {
3722 r.append(' ');
3723 }
3724 r.append(a.info.name);
3725 }
3726 }
3727 if (r != null) {
3728 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3729 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003731 N = pkg.activities.size();
3732 r = null;
3733 for (i=0; i<N; i++) {
3734 PackageParser.Activity a = pkg.activities.get(i);
3735 mActivities.removeActivity(a, "activity");
3736 if (chatty) {
3737 if (r == null) {
3738 r = new StringBuilder(256);
3739 } else {
3740 r.append(' ');
3741 }
3742 r.append(a.info.name);
3743 }
3744 }
3745 if (r != null) {
3746 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3747 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 N = pkg.permissions.size();
3750 r = null;
3751 for (i=0; i<N; i++) {
3752 PackageParser.Permission p = pkg.permissions.get(i);
3753 boolean tree = false;
3754 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3755 if (bp == null) {
3756 tree = true;
3757 bp = mSettings.mPermissionTrees.get(p.info.name);
3758 }
3759 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003760 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 if (chatty) {
3762 if (r == null) {
3763 r = new StringBuilder(256);
3764 } else {
3765 r.append(' ');
3766 }
3767 r.append(p.info.name);
3768 }
3769 }
3770 }
3771 if (r != null) {
3772 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3773 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 N = pkg.instrumentation.size();
3776 r = null;
3777 for (i=0; i<N; i++) {
3778 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003779 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 if (chatty) {
3781 if (r == null) {
3782 r = new StringBuilder(256);
3783 } else {
3784 r.append(' ');
3785 }
3786 r.append(a.info.name);
3787 }
3788 }
3789 if (r != null) {
3790 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3791 }
3792 }
3793 }
3794
3795 private static final boolean isPackageFilename(String name) {
3796 return name != null && name.endsWith(".apk");
3797 }
3798
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003799 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
3800 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
3801 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
3802 return true;
3803 }
3804 }
3805 return false;
3806 }
3807
3808 private void updatePermissionsLP(String changingPkg,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07003809 PackageParser.Package pkgInfo, boolean grantPermissions,
3810 boolean replace, boolean replaceAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 // Make sure there are no dangling permission trees.
3812 Iterator<BasePermission> it = mSettings.mPermissionTrees
3813 .values().iterator();
3814 while (it.hasNext()) {
3815 BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003816 if (bp.packageSetting == null) {
3817 // We may not yet have parsed the package, so just see if
3818 // we still know about its settings.
3819 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3820 }
3821 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003822 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 + " from package " + bp.sourcePackage);
3824 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003825 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3826 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3827 Slog.i(TAG, "Removing old permission tree: " + bp.name
3828 + " from package " + bp.sourcePackage);
3829 grantPermissions = true;
3830 it.remove();
3831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 }
3833 }
3834
3835 // Make sure all dynamic permissions have been assigned to a package,
3836 // and make sure there are no dangling permissions.
3837 it = mSettings.mPermissions.values().iterator();
3838 while (it.hasNext()) {
3839 BasePermission bp = it.next();
3840 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3841 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3842 + bp.name + " pkg=" + bp.sourcePackage
3843 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003844 if (bp.packageSetting == null && bp.pendingInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 BasePermission tree = findPermissionTreeLP(bp.name);
3846 if (tree != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003847 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003848 bp.perm = new PackageParser.Permission(tree.perm.owner,
3849 new PermissionInfo(bp.pendingInfo));
3850 bp.perm.info.packageName = tree.perm.info.packageName;
3851 bp.perm.info.name = bp.name;
3852 bp.uid = tree.uid;
3853 }
3854 }
3855 }
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: " + 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: " + 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 // Now update the permissions for all packages, in particular
3876 // replace the granted permissions of the system packages.
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003877 if (grantPermissions) {
3878 for (PackageParser.Package pkg : mPackages.values()) {
3879 if (pkg != pkgInfo) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07003880 grantPermissionsLP(pkg, replaceAll);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003881 }
3882 }
3883 }
3884
3885 if (pkgInfo != null) {
3886 grantPermissionsLP(pkgInfo, replace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 }
3888 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3891 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3892 if (ps == null) {
3893 return;
3894 }
3895 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003896 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 if (replace) {
3899 ps.permissionsFixed = false;
3900 if (gp == ps) {
3901 gp.grantedPermissions.clear();
3902 gp.gids = mGlobalGids;
3903 }
3904 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 if (gp.gids == null) {
3907 gp.gids = mGlobalGids;
3908 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 final int N = pkg.requestedPermissions.size();
3911 for (int i=0; i<N; i++) {
3912 String name = pkg.requestedPermissions.get(i);
3913 BasePermission bp = mSettings.mPermissions.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 if (false) {
3915 if (gp != ps) {
3916 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003917 + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 }
3919 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003920 if (bp != null && bp.packageSetting != null) {
3921 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003923 boolean allowedSig = false;
3924 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3925 || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07003927 } else if (bp.packageSetting == null) {
3928 // This permission is invalid; skip it.
3929 allowed = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003930 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3931 || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003932 allowed = (checkSignaturesLP(
3933 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003935 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003937 if (!allowed && bp.protectionLevel
3938 == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Kenny Root85387d72010-08-26 10:13:11 -07003939 if (isSystemApp(pkg)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 // For updated system applications, the signatureOrSystem permission
3941 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07003942 if (isUpdatedSystemApp(pkg)) {
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003943 PackageSetting sysPs = mSettings.getDisabledSystemPkg(
3944 pkg.packageName);
3945 final GrantedPermissions origGp = sysPs.sharedUser != null
3946 ? sysPs.sharedUser : sysPs;
3947 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 allowed = true;
3949 } else {
3950 allowed = false;
3951 }
3952 } else {
3953 allowed = true;
3954 }
3955 }
3956 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003957 if (allowed) {
3958 allowedSig = true;
3959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 } else {
3961 allowed = false;
3962 }
3963 if (false) {
3964 if (gp != ps) {
3965 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3966 }
3967 }
3968 if (allowed) {
3969 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3970 && ps.permissionsFixed) {
3971 // If this is an existing, non-system package, then
3972 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07003973 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003975 // Except... if this is a permission that was added
3976 // to the platform (note: need to only do this when
3977 // updating the platform).
3978 final int NP = PackageParser.NEW_PERMISSIONS.length;
3979 for (int ip=0; ip<NP; ip++) {
3980 final PackageParser.NewPermissionInfo npi
3981 = PackageParser.NEW_PERMISSIONS[ip];
3982 if (npi.name.equals(perm)
3983 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3984 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07003985 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003986 + pkg.packageName);
3987 break;
3988 }
3989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 }
3991 }
3992 if (allowed) {
3993 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003994 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 gp.grantedPermissions.add(perm);
3996 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07003997 } else if (!ps.haveGids) {
3998 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 }
4000 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004001 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 + " to package " + pkg.packageName
4003 + " because it was previously installed without");
4004 }
4005 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004006 if (gp.grantedPermissions.remove(perm)) {
4007 changedPermission = true;
4008 gp.gids = removeInts(gp.gids, bp.gids);
4009 Slog.i(TAG, "Un-granting permission " + perm
4010 + " from package " + pkg.packageName
4011 + " (protectionLevel=" + bp.protectionLevel
4012 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4013 + ")");
4014 } else {
4015 Slog.w(TAG, "Not granting permission " + perm
4016 + " to package " + pkg.packageName
4017 + " (protectionLevel=" + bp.protectionLevel
4018 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4019 + ")");
4020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 }
4022 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004023 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 + " in package " + pkg.packageName);
4025 }
4026 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004027
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004028 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004029 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4030 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 // This is the first that we have heard about this package, so the
4032 // permissions we have now selected are fixed until explicitly
4033 // changed.
4034 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004036 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004039 private final class ActivityIntentResolver
4040 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Jason parks1125d782011-01-12 09:47:26 -06004041 @Override
Mihai Preda074edef2009-05-18 17:13:31 +02004042 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004044 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 }
4046
Mihai Preda074edef2009-05-18 17:13:31 +02004047 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004049 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4051 }
4052
Mihai Predaeae850c2009-05-13 10:13:48 +02004053 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4054 ArrayList<PackageParser.Activity> packageActivities) {
4055 if (packageActivities == null) {
4056 return null;
4057 }
4058 mFlags = flags;
4059 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4060 int N = packageActivities.size();
4061 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4062 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004063
4064 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004065 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004066 intentFilters = packageActivities.get(i).intents;
4067 if (intentFilters != null && intentFilters.size() > 0) {
4068 listCut.add(intentFilters);
4069 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004070 }
4071 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4072 }
4073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004075 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004076 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 if (SHOW_INFO || Config.LOGV) Log.v(
4078 TAG, " " + type + " " +
4079 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4080 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4081 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004082 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004083 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004084 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4085 intent.setPriority(0);
4086 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4087 + a.className + " with priority > 0, forcing to 0");
4088 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 if (SHOW_INFO || Config.LOGV) {
4090 Log.v(TAG, " IntentFilter:");
4091 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4092 }
4093 if (!intent.debugCheck()) {
4094 Log.w(TAG, "==> For Activity " + a.info.name);
4095 }
4096 addFilter(intent);
4097 }
4098 }
4099
4100 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004101 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 if (SHOW_INFO || Config.LOGV) Log.v(
4103 TAG, " " + type + " " +
4104 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4105 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4106 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004107 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004108 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
4109 if (SHOW_INFO || Config.LOGV) {
4110 Log.v(TAG, " IntentFilter:");
4111 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4112 }
4113 removeFilter(intent);
4114 }
4115 }
4116
4117 @Override
4118 protected boolean allowFilterResult(
4119 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4120 ActivityInfo filterAi = filter.activity.info;
4121 for (int i=dest.size()-1; i>=0; i--) {
4122 ActivityInfo destAi = dest.get(i).activityInfo;
4123 if (destAi.name == filterAi.name
4124 && destAi.packageName == filterAi.packageName) {
4125 return false;
4126 }
4127 }
4128 return true;
4129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004132 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4133 return info.activity.owner.packageName;
4134 }
4135
4136 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
4138 int match) {
4139 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
4140 return null;
4141 }
4142 final PackageParser.Activity activity = info.activity;
4143 if (mSafeMode && (activity.info.applicationInfo.flags
4144 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4145 return null;
4146 }
4147 final ResolveInfo res = new ResolveInfo();
4148 res.activityInfo = PackageParser.generateActivityInfo(activity,
4149 mFlags);
4150 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4151 res.filter = info;
4152 }
4153 res.priority = info.getPriority();
4154 res.preferredOrder = activity.owner.mPreferredOrder;
4155 //System.out.println("Result: " + res.activityInfo.className +
4156 // " = " + res.priority);
4157 res.match = match;
4158 res.isDefault = info.hasDefault;
4159 res.labelRes = info.labelRes;
4160 res.nonLocalizedLabel = info.nonLocalizedLabel;
4161 res.icon = info.icon;
4162 return res;
4163 }
4164
4165 @Override
4166 protected void sortResults(List<ResolveInfo> results) {
4167 Collections.sort(results, mResolvePrioritySorter);
4168 }
4169
4170 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004171 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004173 out.print(prefix); out.print(
4174 Integer.toHexString(System.identityHashCode(filter.activity)));
4175 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004176 out.print(filter.activity.getComponentShortName());
4177 out.print(" filter ");
4178 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 }
4180
4181// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4182// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4183// final List<ResolveInfo> retList = Lists.newArrayList();
4184// while (i.hasNext()) {
4185// final ResolveInfo resolveInfo = i.next();
4186// if (isEnabledLP(resolveInfo.activityInfo)) {
4187// retList.add(resolveInfo);
4188// }
4189// }
4190// return retList;
4191// }
4192
4193 // Keys are String (activity class name), values are Activity.
4194 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4195 = new HashMap<ComponentName, PackageParser.Activity>();
4196 private int mFlags;
4197 }
4198
4199 private final class ServiceIntentResolver
4200 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Jason parks1125d782011-01-12 09:47:26 -06004201 @Override
Mihai Preda074edef2009-05-18 17:13:31 +02004202 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004204 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
4206
Mihai Preda074edef2009-05-18 17:13:31 +02004207 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004209 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004210 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4211 }
4212
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07004213 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4214 ArrayList<PackageParser.Service> packageServices) {
4215 if (packageServices == null) {
4216 return null;
4217 }
4218 mFlags = flags;
4219 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4220 int N = packageServices.size();
4221 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4222 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4223
4224 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4225 for (int i = 0; i < N; ++i) {
4226 intentFilters = packageServices.get(i).intents;
4227 if (intentFilters != null && intentFilters.size() > 0) {
4228 listCut.add(intentFilters);
4229 }
4230 }
4231 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4232 }
4233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004235 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 if (SHOW_INFO || Config.LOGV) Log.v(
4237 TAG, " " + (s.info.nonLocalizedLabel != null
4238 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4239 if (SHOW_INFO || Config.LOGV) Log.v(
4240 TAG, " Class=" + s.info.name);
4241 int NI = s.intents.size();
4242 int j;
4243 for (j=0; j<NI; j++) {
4244 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4245 if (SHOW_INFO || Config.LOGV) {
4246 Log.v(TAG, " IntentFilter:");
4247 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4248 }
4249 if (!intent.debugCheck()) {
4250 Log.w(TAG, "==> For Service " + s.info.name);
4251 }
4252 addFilter(intent);
4253 }
4254 }
4255
4256 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004257 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 if (SHOW_INFO || Config.LOGV) Log.v(
4259 TAG, " " + (s.info.nonLocalizedLabel != null
4260 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4261 if (SHOW_INFO || Config.LOGV) Log.v(
4262 TAG, " Class=" + s.info.name);
4263 int NI = s.intents.size();
4264 int j;
4265 for (j=0; j<NI; j++) {
4266 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4267 if (SHOW_INFO || Config.LOGV) {
4268 Log.v(TAG, " IntentFilter:");
4269 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4270 }
4271 removeFilter(intent);
4272 }
4273 }
4274
4275 @Override
4276 protected boolean allowFilterResult(
4277 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4278 ServiceInfo filterSi = filter.service.info;
4279 for (int i=dest.size()-1; i>=0; i--) {
4280 ServiceInfo destAi = dest.get(i).serviceInfo;
4281 if (destAi.name == filterSi.name
4282 && destAi.packageName == filterSi.packageName) {
4283 return false;
4284 }
4285 }
4286 return true;
4287 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004290 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
4291 return info.service.owner.packageName;
4292 }
4293
4294 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4296 int match) {
Jason parks1125d782011-01-12 09:47:26 -06004297 final PackageParser.ServiceIntentInfo info = filter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4299 return null;
4300 }
4301 final PackageParser.Service service = info.service;
4302 if (mSafeMode && (service.info.applicationInfo.flags
4303 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4304 return null;
4305 }
4306 final ResolveInfo res = new ResolveInfo();
4307 res.serviceInfo = PackageParser.generateServiceInfo(service,
4308 mFlags);
4309 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4310 res.filter = filter;
4311 }
4312 res.priority = info.getPriority();
4313 res.preferredOrder = service.owner.mPreferredOrder;
4314 //System.out.println("Result: " + res.activityInfo.className +
4315 // " = " + res.priority);
4316 res.match = match;
4317 res.isDefault = info.hasDefault;
4318 res.labelRes = info.labelRes;
4319 res.nonLocalizedLabel = info.nonLocalizedLabel;
4320 res.icon = info.icon;
4321 return res;
4322 }
4323
4324 @Override
4325 protected void sortResults(List<ResolveInfo> results) {
4326 Collections.sort(results, mResolvePrioritySorter);
4327 }
4328
4329 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004330 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004332 out.print(prefix); out.print(
4333 Integer.toHexString(System.identityHashCode(filter.service)));
4334 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004335 out.print(filter.service.getComponentShortName());
4336 out.print(" filter ");
4337 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 }
4339
4340// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4341// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4342// final List<ResolveInfo> retList = Lists.newArrayList();
4343// while (i.hasNext()) {
4344// final ResolveInfo resolveInfo = (ResolveInfo) i;
4345// if (isEnabledLP(resolveInfo.serviceInfo)) {
4346// retList.add(resolveInfo);
4347// }
4348// }
4349// return retList;
4350// }
4351
4352 // Keys are String (activity class name), values are Activity.
4353 private final HashMap<ComponentName, PackageParser.Service> mServices
4354 = new HashMap<ComponentName, PackageParser.Service>();
4355 private int mFlags;
4356 };
4357
4358 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4359 new Comparator<ResolveInfo>() {
4360 public int compare(ResolveInfo r1, ResolveInfo r2) {
4361 int v1 = r1.priority;
4362 int v2 = r2.priority;
4363 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4364 if (v1 != v2) {
4365 return (v1 > v2) ? -1 : 1;
4366 }
4367 v1 = r1.preferredOrder;
4368 v2 = r2.preferredOrder;
4369 if (v1 != v2) {
4370 return (v1 > v2) ? -1 : 1;
4371 }
4372 if (r1.isDefault != r2.isDefault) {
4373 return r1.isDefault ? -1 : 1;
4374 }
4375 v1 = r1.match;
4376 v2 = r2.match;
4377 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4378 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4379 }
4380 };
4381
4382 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4383 new Comparator<ProviderInfo>() {
4384 public int compare(ProviderInfo p1, ProviderInfo p2) {
4385 final int v1 = p1.initOrder;
4386 final int v2 = p2.initOrder;
4387 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4388 }
4389 };
4390
Kenny Root93565c4b2010-06-18 15:46:06 -07004391 private static final boolean DEBUG_OBB = false;
4392
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004393 private static final void sendPackageBroadcast(String action, String pkg,
4394 Bundle extras, IIntentReceiver finishedReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004395 IActivityManager am = ActivityManagerNative.getDefault();
4396 if (am != null) {
4397 try {
4398 final Intent intent = new Intent(action,
4399 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4400 if (extras != null) {
4401 intent.putExtras(extras);
4402 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004403 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004404 am.broadcastIntent(null, intent, null, finishedReceiver,
4405 0, null, null, null, finishedReceiver != null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 } catch (RemoteException ex) {
4407 }
4408 }
4409 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004410
4411 public String nextPackageToClean(String lastPackage) {
4412 synchronized (mPackages) {
4413 if (!mMediaMounted) {
4414 // If the external storage is no longer mounted at this point,
4415 // the caller may not have been able to delete all of this
4416 // packages files and can not delete any more. Bail.
4417 return null;
4418 }
4419 if (lastPackage != null) {
4420 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4421 }
4422 return mSettings.mPackagesToBeCleaned.size() > 0
4423 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4424 }
4425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004427 void schedulePackageCleaning(String packageName) {
4428 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4429 }
4430
4431 void startCleaningPackages() {
4432 synchronized (mPackages) {
4433 if (!mMediaMounted) {
4434 return;
4435 }
4436 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4437 return;
4438 }
4439 }
4440 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4441 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4442 IActivityManager am = ActivityManagerNative.getDefault();
4443 if (am != null) {
4444 try {
4445 am.startService(null, intent, null);
4446 } catch (RemoteException e) {
4447 }
4448 }
4449 }
4450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 private final class AppDirObserver extends FileObserver {
4452 public AppDirObserver(String path, int mask, boolean isrom) {
4453 super(path, mask);
4454 mRootDir = path;
4455 mIsRom = isrom;
4456 }
4457
Jason parks1125d782011-01-12 09:47:26 -06004458 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004459 public void onEvent(int event, String path) {
4460 String removedPackage = null;
4461 int removedUid = -1;
4462 String addedPackage = null;
4463 int addedUid = -1;
4464
4465 synchronized (mInstallLock) {
4466 String fullPathStr = null;
4467 File fullPath = null;
4468 if (path != null) {
4469 fullPath = new File(mRootDir, path);
4470 fullPathStr = fullPath.getPath();
4471 }
4472
4473 if (Config.LOGV) Log.v(
4474 TAG, "File " + fullPathStr + " changed: "
4475 + Integer.toHexString(event));
4476
4477 if (!isPackageFilename(path)) {
4478 if (Config.LOGV) Log.v(
4479 TAG, "Ignoring change of non-package file: " + fullPathStr);
4480 return;
4481 }
4482
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004483 // Ignore packages that are being installed or
4484 // have just been installed.
4485 if (ignoreCodePath(fullPathStr)) {
4486 return;
4487 }
4488 PackageParser.Package p = null;
4489 synchronized (mPackages) {
4490 p = mAppDirs.get(fullPathStr);
4491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004493 if (p != null) {
4494 removePackageLI(p, true);
4495 removedPackage = p.applicationInfo.packageName;
4496 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 }
4498 }
4499
4500 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004502 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004503 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
4504 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 PackageParser.PARSE_CHATTY |
4506 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004507 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
4508 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 if (p != null) {
4510 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004511 updatePermissionsLP(p.packageName, p,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07004512 p.permissions.size() > 0, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 }
4514 addedPackage = p.applicationInfo.packageName;
4515 addedUid = p.applicationInfo.uid;
4516 }
4517 }
4518 }
4519
4520 synchronized (mPackages) {
4521 mSettings.writeLP();
4522 }
4523 }
4524
4525 if (removedPackage != null) {
4526 Bundle extras = new Bundle(1);
4527 extras.putInt(Intent.EXTRA_UID, removedUid);
4528 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004529 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
4530 extras, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 }
4532 if (addedPackage != null) {
4533 Bundle extras = new Bundle(1);
4534 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004535 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
4536 extras, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 }
4538 }
4539
4540 private final String mRootDir;
4541 private final boolean mIsRom;
4542 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 /* Called when a downloaded package installation has been confirmed by the user */
4545 public void installPackage(
4546 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004547 installPackage(packageURI, observer, flags, null);
4548 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004549
Jacek Surazski65e13172009-04-28 15:26:38 +02004550 /* Called when a downloaded package installation has been confirmed by the user */
4551 public void installPackage(
4552 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4553 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 mContext.enforceCallingOrSelfPermission(
4555 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004556
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004557 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004558 msg.obj = new InstallParams(packageURI, observer, flags,
4559 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004560 mHandler.sendMessage(msg);
4561 }
4562
Christopher Tate1bb69062010-02-19 17:02:12 -08004563 public void finishPackageInstall(int token) {
4564 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4565 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4566 mHandler.sendMessage(msg);
4567 }
4568
Dianne Hackborn880119b2010-11-18 22:26:40 -08004569 public void setInstallerPackageName(String targetPackage,
4570 String installerPackageName) {
4571 PackageSetting pkgSetting;
4572 final int uid = Binder.getCallingUid();
4573 final int permission = mContext.checkCallingPermission(
4574 android.Manifest.permission.INSTALL_PACKAGES);
4575 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4576 synchronized (mPackages) {
4577 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
4578 if (targetPackageSetting == null) {
4579 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
4580 }
4581
4582 PackageSetting installerPackageSetting;
4583 if (installerPackageName != null) {
4584 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
4585 if (installerPackageSetting == null) {
4586 throw new IllegalArgumentException("Unknown installer package: "
4587 + installerPackageName);
4588 }
4589 } else {
4590 installerPackageSetting = null;
4591 }
4592
4593 Signature[] callerSignature;
4594 Object obj = mSettings.getUserIdLP(uid);
4595 if (obj != null) {
4596 if (obj instanceof SharedUserSetting) {
4597 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
4598 } else if (obj instanceof PackageSetting) {
4599 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
4600 } else {
4601 throw new SecurityException("Bad object " + obj + " for uid " + uid);
4602 }
4603 } else {
4604 throw new SecurityException("Unknown calling uid " + uid);
4605 }
4606
4607 // Verify: can't set installerPackageName to a package that is
4608 // not signed with the same cert as the caller.
4609 if (installerPackageSetting != null) {
4610 if (checkSignaturesLP(callerSignature,
4611 installerPackageSetting.signatures.mSignatures)
4612 != PackageManager.SIGNATURE_MATCH) {
4613 throw new SecurityException(
4614 "Caller does not have same cert as new installer package "
4615 + installerPackageName);
4616 }
4617 }
4618
4619 // Verify: if target already has an installer package, it must
4620 // be signed with the same cert as the caller.
4621 if (targetPackageSetting.installerPackageName != null) {
4622 PackageSetting setting = mSettings.mPackages.get(
4623 targetPackageSetting.installerPackageName);
4624 // If the currently set package isn't valid, then it's always
4625 // okay to change it.
4626 if (setting != null) {
4627 if (checkSignaturesLP(callerSignature,
4628 setting.signatures.mSignatures)
4629 != PackageManager.SIGNATURE_MATCH) {
4630 throw new SecurityException(
4631 "Caller does not have same cert as old installer package "
4632 + targetPackageSetting.installerPackageName);
4633 }
4634 }
4635 }
4636
4637 // Okay!
4638 targetPackageSetting.installerPackageName = installerPackageName;
4639 scheduleWriteSettingsLocked();
4640 }
4641 }
4642
Kenny Root93565c4b2010-06-18 15:46:06 -07004643 public void setPackageObbPath(String packageName, String path) {
4644 if (DEBUG_OBB)
4645 Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path);
4646 PackageSetting pkgSetting;
4647 final int uid = Binder.getCallingUid();
Kenny Roote059b272010-07-12 08:36:07 -07004648 final int permission = mContext.checkCallingPermission(
4649 android.Manifest.permission.INSTALL_PACKAGES);
4650 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Kenny Root93565c4b2010-06-18 15:46:06 -07004651 synchronized (mPackages) {
4652 pkgSetting = mSettings.mPackages.get(packageName);
4653 if (pkgSetting == null) {
4654 throw new IllegalArgumentException("Unknown package: " + packageName);
4655 }
4656 if (!allowedByPermission && (uid != pkgSetting.userId)) {
4657 throw new SecurityException("Permission denial: attempt to set .obb file from pid="
4658 + Binder.getCallingPid() + ", uid=" + uid + ", package uid="
4659 + pkgSetting.userId);
4660 }
4661 pkgSetting.obbPathString = path;
4662 mSettings.writeLP();
4663 }
4664 }
4665
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004666 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 // Queue up an async operation since the package installation may take a little while.
4668 mHandler.post(new Runnable() {
4669 public void run() {
4670 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004671 // Result object to be returned
4672 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004673 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004674 res.uid = -1;
4675 res.pkg = null;
4676 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004677 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004678 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004679 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004680 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004681 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004682 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004684
4685 // A restore should be performed at this point if (a) the install
4686 // succeeded, (b) the operation is not an update, and (c) the new
4687 // package has a backupAgent defined.
4688 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004689 boolean doRestore = (!update
4690 && res.pkg != null
4691 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004692
4693 // Set up the post-install work request bookkeeping. This will be used
4694 // and cleaned up by the post-install event handling regardless of whether
4695 // there's a restore pass performed. Token values are >= 1.
4696 int token;
4697 if (mNextInstallToken < 0) mNextInstallToken = 1;
4698 token = mNextInstallToken++;
4699
4700 PostInstallData data = new PostInstallData(args, res);
4701 mRunningInstalls.put(token, data);
4702 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4703
4704 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4705 // Pass responsibility to the Backup Manager. It will perform a
4706 // restore if appropriate, then pass responsibility back to the
4707 // Package Manager to run the post-install observer callbacks
4708 // and broadcasts.
4709 IBackupManager bm = IBackupManager.Stub.asInterface(
4710 ServiceManager.getService(Context.BACKUP_SERVICE));
4711 if (bm != null) {
4712 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4713 + " to BM for possible restore");
4714 try {
4715 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4716 } catch (RemoteException e) {
4717 // can't happen; the backup manager is local
4718 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004719 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08004720 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004721 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004722 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004723 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08004724 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004726 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004727
4728 if (!doRestore) {
4729 // No restore possible, or the Backup Manager was mysteriously not
4730 // available -- just fire the post-install work request directly.
4731 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4732 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4733 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 }
4736 });
4737 }
4738
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004739 abstract class HandlerParams {
4740 final static int MAX_RETRIES = 4;
4741 int retry = 0;
4742 final void startCopy() {
4743 try {
4744 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
4745 retry++;
4746 if (retry > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004747 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004748 mHandler.sendEmptyMessage(MCS_GIVE_UP);
4749 handleServiceError();
4750 return;
4751 } else {
4752 handleStartCopy();
4753 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
4754 mHandler.sendEmptyMessage(MCS_UNBIND);
4755 }
4756 } catch (RemoteException e) {
4757 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
4758 mHandler.sendEmptyMessage(MCS_RECONNECT);
4759 }
4760 handleReturnCode();
4761 }
4762
4763 final void serviceError() {
4764 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
4765 handleServiceError();
4766 handleReturnCode();
4767 }
4768 abstract void handleStartCopy() throws RemoteException;
4769 abstract void handleServiceError();
4770 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004771 }
4772
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004773 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004774 final IPackageInstallObserver observer;
4775 int flags;
4776 final Uri packageURI;
4777 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004778 private InstallArgs mArgs;
4779 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004780 InstallParams(Uri packageURI,
4781 IPackageInstallObserver observer, int flags,
4782 String installerPackageName) {
4783 this.packageURI = packageURI;
4784 this.flags = flags;
4785 this.observer = observer;
4786 this.installerPackageName = installerPackageName;
4787 }
4788
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004789 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
4790 String packageName = pkgLite.packageName;
4791 int installLocation = pkgLite.installLocation;
4792 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
4793 synchronized (mPackages) {
4794 PackageParser.Package pkg = mPackages.get(packageName);
4795 if (pkg != null) {
4796 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
4797 // Check for updated system application.
4798 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4799 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004800 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004801 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
4802 }
4803 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4804 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004805 if (onSd) {
4806 // Install flag overrides everything.
4807 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4808 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004809 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004810 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
4811 // Application explicitly specified internal.
4812 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4813 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
4814 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004815 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004816 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07004817 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004818 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4819 }
4820 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004821 }
4822 }
4823 } else {
4824 // Invalid install. Return error code
4825 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
4826 }
4827 }
4828 }
4829 // All the special cases have been taken care of.
4830 // Return result based on recommended install location.
4831 if (onSd) {
4832 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4833 }
4834 return pkgLite.recommendedInstallLocation;
4835 }
4836
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004837 /*
4838 * Invoke remote method to get package information and install
4839 * location values. Override install location based on default
4840 * policy if needed and then create install arguments based
4841 * on the install location.
4842 */
Jason parks1125d782011-01-12 09:47:26 -06004843 @Override
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004844 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004845 int ret = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004846 boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
4847 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004848 boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
4849 if (onInt && onSd) {
4850 // Check if both bits are set.
4851 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
4852 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4853 } else if (fwdLocked && onSd) {
4854 // Check for forward locked apps
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004855 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004856 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004857 } else {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004858 // Remote call to find out default install location
Kenny Root11128572010-10-11 10:51:32 -07004859 final PackageInfoLite pkgLite;
4860 try {
4861 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
4862 Intent.FLAG_GRANT_READ_URI_PERMISSION);
4863 pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
4864 } finally {
4865 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
4866 }
4867
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004868 int loc = pkgLite.recommendedInstallLocation;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004869 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
4870 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4871 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
4872 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4873 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004874 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4875 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
4876 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004877 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
4878 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004879 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004880 // Override with defaults if needed.
4881 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004882 if (!onSd && !onInt) {
4883 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004884 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
4885 // Set the flag to install on external media.
4886 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004887 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004888 } else {
4889 // Make sure the flag for installing on external
4890 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004891 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004892 flags &= ~PackageManager.INSTALL_EXTERNAL;
4893 }
4894 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004895 }
4896 }
4897 // Create the file args now.
4898 mArgs = createInstallArgs(this);
4899 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4900 // Create copy only if we are not in an erroneous state.
4901 // Remote call to initiate copy using temporary file
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004902 ret = mArgs.copyApk(mContainerService, true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004903 }
4904 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004905 }
4906
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004907 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004908 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07004909 // If mArgs is null, then MCS couldn't be reached. When it
4910 // reconnects, it will try again to install. At that point, this
4911 // will succeed.
4912 if (mArgs != null) {
4913 processPendingInstall(mArgs, mRet);
4914 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004915 }
4916
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004917 @Override
4918 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004919 mArgs = createInstallArgs(this);
4920 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004921 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004922 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004923
4924 /*
4925 * Utility class used in movePackage api.
4926 * srcArgs and targetArgs are not set for invalid flags and make
4927 * sure to do null checks when invoking methods on them.
4928 * We probably want to return ErrorPrams for both failed installs
4929 * and moves.
4930 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004931 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004932 final IPackageMoveObserver observer;
4933 final int flags;
4934 final String packageName;
4935 final InstallArgs srcArgs;
4936 final InstallArgs targetArgs;
4937 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07004938
4939 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
4940 String packageName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004941 this.srcArgs = srcArgs;
4942 this.observer = observer;
4943 this.flags = flags;
4944 this.packageName = packageName;
4945 if (srcArgs != null) {
4946 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07004947 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004948 } else {
4949 targetArgs = null;
4950 }
4951 }
4952
Jason parks1125d782011-01-12 09:47:26 -06004953 @Override
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004954 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004955 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4956 // Check for storage space on target medium
4957 if (!targetArgs.checkFreeStorage(mContainerService)) {
4958 Log.w(TAG, "Insufficient storage to install");
4959 return;
4960 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004961 // Create the file args now.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004962 mRet = targetArgs.copyApk(mContainerService, false);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004963 targetArgs.doPreInstall(mRet);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004964 if (DEBUG_SD_INSTALL) {
4965 StringBuilder builder = new StringBuilder();
4966 if (srcArgs != null) {
4967 builder.append("src: ");
4968 builder.append(srcArgs.getCodePath());
4969 }
4970 if (targetArgs != null) {
4971 builder.append(" target : ");
4972 builder.append(targetArgs.getCodePath());
4973 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004974 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004975 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004976 }
4977
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004978 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004979 void handleReturnCode() {
4980 targetArgs.doPostInstall(mRet);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004981 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
4982 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
4983 currentStatus = PackageManager.MOVE_SUCCEEDED;
4984 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
4985 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
4986 }
4987 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004988 }
4989
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004990 @Override
4991 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004992 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004993 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004994 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004995
4996 private InstallArgs createInstallArgs(InstallParams params) {
4997 if (installOnSd(params.flags)) {
4998 return new SdInstallArgs(params);
4999 } else {
5000 return new FileInstallArgs(params);
5001 }
5002 }
5003
Kenny Root85387d72010-08-26 10:13:11 -07005004 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
5005 String nativeLibraryPath) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005006 if (installOnSd(flags)) {
Kenny Root85387d72010-08-26 10:13:11 -07005007 return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005008 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005009 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005010 }
5011 }
5012
Kenny Root85387d72010-08-26 10:13:11 -07005013 // Used by package mover
5014 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005015 if (installOnSd(flags)) {
5016 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
5017 return new SdInstallArgs(packageURI, cid);
5018 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005019 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005020 }
5021 }
5022
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005023 static abstract class InstallArgs {
5024 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005025 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005026 final int flags;
5027 final Uri packageURI;
5028 final String installerPackageName;
5029
5030 InstallArgs(Uri packageURI,
5031 IPackageInstallObserver observer, int flags,
5032 String installerPackageName) {
5033 this.packageURI = packageURI;
5034 this.flags = flags;
5035 this.observer = observer;
5036 this.installerPackageName = installerPackageName;
5037 }
5038
5039 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005040 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005041 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005042 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005043 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005044 abstract String getCodePath();
5045 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07005046 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005047 // Need installer lock especially for dex file removal.
5048 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005049 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005050 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005051 }
5052
5053 class FileInstallArgs extends InstallArgs {
5054 File installDir;
5055 String codeFileName;
5056 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07005057 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005058 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005059
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005060 FileInstallArgs(InstallParams params) {
5061 super(params.packageURI, params.observer,
5062 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005063 }
5064
Kenny Root85387d72010-08-26 10:13:11 -07005065 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005066 super(null, null, 0, null);
5067 File codeFile = new File(fullCodePath);
5068 installDir = codeFile.getParentFile();
5069 codeFileName = fullCodePath;
5070 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07005071 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005072 }
5073
Kenny Root85387d72010-08-26 10:13:11 -07005074 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005075 super(packageURI, null, 0, null);
Kenny Root85387d72010-08-26 10:13:11 -07005076 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005077 String apkName = getNextCodePath(null, pkgName, ".apk");
5078 codeFileName = new File(installDir, apkName + ".apk").getPath();
5079 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07005080 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005081 }
5082
Jason parks1125d782011-01-12 09:47:26 -06005083 @Override
Kenny Root11128572010-10-11 10:51:32 -07005084 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5085 try {
5086 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5087 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5088 return imcs.checkFreeStorage(false, packageURI);
5089 } finally {
5090 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5091 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005092 }
5093
Jason parks1125d782011-01-12 09:47:26 -06005094 @Override
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005095 String getCodePath() {
5096 return codeFileName;
5097 }
5098
Jason parks1125d782011-01-12 09:47:26 -06005099 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005100 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07005101 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005102 codeFileName = createTempPackageFile(installDir).getPath();
5103 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005104 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005105 }
5106
Jason parks1125d782011-01-12 09:47:26 -06005107 @Override
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005108 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005109 if (temp) {
5110 // Generate temp file name
5111 createCopyFile();
5112 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005113 // Get a ParcelFileDescriptor to write to the output file
5114 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005115 if (!created) {
5116 try {
5117 codeFile.createNewFile();
5118 // Set permissions
5119 if (!setPermissions()) {
5120 // Failed setting permissions.
5121 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5122 }
5123 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005124 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005125 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5126 }
5127 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005128 ParcelFileDescriptor out = null;
5129 try {
Kenny Root85387d72010-08-26 10:13:11 -07005130 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005131 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005132 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005133 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5134 }
5135 // Copy the resource now
5136 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5137 try {
Kenny Root11128572010-10-11 10:51:32 -07005138 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5139 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005140 if (imcs.copyResource(packageURI, out)) {
5141 ret = PackageManager.INSTALL_SUCCEEDED;
5142 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005143 } finally {
5144 try { if (out != null) out.close(); } catch (IOException e) {}
Kenny Root11128572010-10-11 10:51:32 -07005145 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005146 }
Kenny Root85387d72010-08-26 10:13:11 -07005147
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005148 return ret;
5149 }
5150
Jason parks1125d782011-01-12 09:47:26 -06005151 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005152 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005153 if (status != PackageManager.INSTALL_SUCCEEDED) {
5154 cleanUp();
5155 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005156 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005157 }
5158
Jason parks1125d782011-01-12 09:47:26 -06005159 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005160 boolean doRename(int status, final String pkgName, String oldCodePath) {
5161 if (status != PackageManager.INSTALL_SUCCEEDED) {
5162 cleanUp();
5163 return false;
5164 } else {
5165 // Rename based on packageName
5166 File codeFile = new File(getCodePath());
5167 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
5168 File desFile = new File(installDir, apkName + ".apk");
5169 if (!codeFile.renameTo(desFile)) {
5170 return false;
5171 }
5172 // Reset paths since the file has been renamed.
5173 codeFileName = desFile.getPath();
5174 resourceFileName = getResourcePathFromCodePath();
5175 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005176 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005177 // Failed setting permissions.
5178 return false;
5179 }
5180 return true;
5181 }
5182 }
5183
Jason parks1125d782011-01-12 09:47:26 -06005184 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005185 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005186 if (status != PackageManager.INSTALL_SUCCEEDED) {
5187 cleanUp();
5188 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005189 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005190 }
5191
Jason parks1125d782011-01-12 09:47:26 -06005192 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005193 String getResourcePath() {
5194 return resourceFileName;
5195 }
5196
5197 String getResourcePathFromCodePath() {
5198 String codePath = getCodePath();
5199 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
5200 String apkNameOnly = getApkName(codePath);
5201 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
5202 } else {
5203 return codePath;
5204 }
5205 }
5206
Kenny Root85387d72010-08-26 10:13:11 -07005207 @Override
5208 String getNativeLibraryPath() {
5209 return libraryPath;
5210 }
5211
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005212 private boolean cleanUp() {
5213 boolean ret = true;
5214 String sourceDir = getCodePath();
5215 String publicSourceDir = getResourcePath();
5216 if (sourceDir != null) {
5217 File sourceFile = new File(sourceDir);
5218 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005219 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005220 ret = false;
5221 }
5222 // Delete application's code and resources
5223 sourceFile.delete();
5224 }
5225 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
5226 final File publicSourceFile = new File(publicSourceDir);
5227 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005228 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005229 }
5230 if (publicSourceFile.exists()) {
5231 publicSourceFile.delete();
5232 }
5233 }
5234 return ret;
5235 }
5236
Jason parks1125d782011-01-12 09:47:26 -06005237 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005238 void cleanUpResourcesLI() {
5239 String sourceDir = getCodePath();
5240 if (cleanUp() && mInstaller != null) {
5241 int retCode = mInstaller.rmdex(sourceDir);
5242 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005243 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005244 + " at location "
5245 + sourceDir + ", retcode=" + retCode);
5246 // we don't consider this to be a failure of the core package deletion
5247 }
5248 }
5249 }
5250
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005251 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005252 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07005253 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005254 final int filePermissions =
5255 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
5256 |FileUtils.S_IROTH;
5257 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
5258 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005259 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005260 getCodePath()
5261 + ". The return code was: " + retCode);
5262 // TODO Define new internal error
5263 return false;
5264 }
5265 return true;
5266 }
5267 return true;
5268 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005269
Jason parks1125d782011-01-12 09:47:26 -06005270 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005271 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07005272 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005273 cleanUpResourcesLI();
5274 return true;
5275 }
Kenny Root85387d72010-08-26 10:13:11 -07005276
5277 private boolean isFwdLocked() {
5278 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5279 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005280 }
5281
5282 class SdInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005283 static final String RES_FILE_NAME = "pkg.apk";
5284
Kenny Root85387d72010-08-26 10:13:11 -07005285 String cid;
5286 String packagePath;
5287 String libraryPath;
5288
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005289 SdInstallArgs(InstallParams params) {
5290 super(params.packageURI, params.observer,
5291 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005292 }
5293
Kenny Root85387d72010-08-26 10:13:11 -07005294 SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005295 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005296 // Extract cid from fullCodePath
5297 int eidx = fullCodePath.lastIndexOf("/");
5298 String subStr1 = fullCodePath.substring(0, eidx);
5299 int sidx = subStr1.lastIndexOf("/");
5300 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07005301 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005302 }
5303
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005304 SdInstallArgs(String cid) {
Dianne Hackbornaa77de12010-05-14 22:33:54 -07005305 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
5306 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07005307 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005308 }
5309
5310 SdInstallArgs(Uri packageURI, String cid) {
5311 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005312 this.cid = cid;
5313 }
5314
Jason parks1125d782011-01-12 09:47:26 -06005315 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005316 void createCopyFile() {
5317 cid = getTempContainerId();
5318 }
5319
Jason parks1125d782011-01-12 09:47:26 -06005320 @Override
Kenny Root11128572010-10-11 10:51:32 -07005321 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5322 try {
5323 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5324 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5325 return imcs.checkFreeStorage(true, packageURI);
5326 } finally {
5327 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5328 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005329 }
5330
Jason parks1125d782011-01-12 09:47:26 -06005331 @Override
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005332 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005333 if (temp) {
5334 createCopyFile();
5335 }
Kenny Root11128572010-10-11 10:51:32 -07005336
5337 final String newCachePath;
5338 try {
5339 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5340 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5341 newCachePath = imcs.copyResourceToContainer(packageURI, cid,
5342 getEncryptKey(), RES_FILE_NAME);
5343 } finally {
5344 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5345 }
5346
Kenny Root85387d72010-08-26 10:13:11 -07005347 if (newCachePath != null) {
5348 setCachePath(newCachePath);
5349 return PackageManager.INSTALL_SUCCEEDED;
5350 } else {
5351 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5352 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005353 }
5354
5355 @Override
5356 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005357 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005358 }
5359
5360 @Override
5361 String getResourcePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005362 return packagePath;
5363 }
5364
5365 @Override
5366 String getNativeLibraryPath() {
5367 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005368 }
5369
Jason parks1125d782011-01-12 09:47:26 -06005370 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005371 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005372 if (status != PackageManager.INSTALL_SUCCEEDED) {
5373 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005374 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005375 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005376 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005377 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07005378 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
5379 Process.SYSTEM_UID);
5380 if (newCachePath != null) {
5381 setCachePath(newCachePath);
5382 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005383 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5384 }
5385 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005386 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005387 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005388 }
5389
Jason parks1125d782011-01-12 09:47:26 -06005390 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005391 boolean doRename(int status, final String pkgName,
5392 String oldCodePath) {
5393 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005394 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005395 if (PackageHelper.isContainerMounted(cid)) {
5396 // Unmount the container
5397 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005398 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005399 return false;
5400 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005401 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005402 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07005403 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
5404 " which might be stale. Will try to clean up.");
5405 // Clean up the stale container and proceed to recreate.
5406 if (!PackageHelper.destroySdDir(newCacheId)) {
5407 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
5408 return false;
5409 }
5410 // Successfully cleaned up stale container. Try to rename again.
5411 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
5412 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
5413 + " inspite of cleaning it up.");
5414 return false;
5415 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005416 }
5417 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005418 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005419 newCachePath = PackageHelper.mountSdDir(newCacheId,
5420 getEncryptKey(), Process.SYSTEM_UID);
5421 } else {
5422 newCachePath = PackageHelper.getSdDir(newCacheId);
5423 }
5424 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005425 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005426 return false;
5427 }
5428 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07005429 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005430 " at new path: " + newCachePath);
5431 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07005432 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005433 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005434 }
5435
Kenny Root85387d72010-08-26 10:13:11 -07005436 private void setCachePath(String newCachePath) {
5437 File cachePath = new File(newCachePath);
5438 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
5439 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
5440 }
5441
Jason parks1125d782011-01-12 09:47:26 -06005442 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005443 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005444 if (status != PackageManager.INSTALL_SUCCEEDED) {
5445 cleanUp();
5446 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005447 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005448 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005449 PackageHelper.mountSdDir(cid,
5450 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005451 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005452 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005453 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005454 }
5455
5456 private void cleanUp() {
5457 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005458 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005459 }
5460
Jason parks1125d782011-01-12 09:47:26 -06005461 @Override
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005462 void cleanUpResourcesLI() {
5463 String sourceFile = getCodePath();
5464 // Remove dex file
5465 if (mInstaller != null) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005466 int retCode = mInstaller.rmdex(sourceFile);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005467 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005468 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005469 + " at location "
5470 + sourceFile.toString() + ", retcode=" + retCode);
5471 // we don't consider this to be a failure of the core package deletion
5472 }
5473 }
5474 cleanUp();
5475 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005476
5477 boolean matchContainer(String app) {
5478 if (cid.startsWith(app)) {
5479 return true;
5480 }
5481 return false;
5482 }
5483
5484 String getPackageName() {
5485 int idx = cid.lastIndexOf("-");
5486 if (idx == -1) {
5487 return cid;
5488 }
5489 return cid.substring(0, idx);
5490 }
5491
Jason parks1125d782011-01-12 09:47:26 -06005492 @Override
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005493 boolean doPostDeleteLI(boolean delete) {
5494 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005495 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005496 if (mounted) {
5497 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005498 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005499 }
5500 if (ret && delete) {
5501 cleanUpResourcesLI();
5502 }
5503 return ret;
5504 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005505 };
5506
5507 // Utility method used to create code paths based on package name and available index.
5508 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
5509 String idxStr = "";
5510 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005511 // Fall back to default value of idx=1 if prefix is not
5512 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005513 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005514 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005515 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005516 if (subStr.endsWith(suffix)) {
5517 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005518 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005519 // If oldCodePath already contains prefix find out the
5520 // ending index to either increment or decrement.
5521 int sidx = subStr.lastIndexOf(prefix);
5522 if (sidx != -1) {
5523 subStr = subStr.substring(sidx + prefix.length());
5524 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005525 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5526 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005527 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005528 try {
5529 idx = Integer.parseInt(subStr);
5530 if (idx <= 1) {
5531 idx++;
5532 } else {
5533 idx--;
5534 }
5535 } catch(NumberFormatException e) {
5536 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005537 }
5538 }
5539 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005540 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005541 return prefix + idxStr;
5542 }
5543
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005544 // Utility method used to ignore ADD/REMOVE events
5545 // by directory observer.
5546 private static boolean ignoreCodePath(String fullPathStr) {
5547 String apkName = getApkName(fullPathStr);
5548 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5549 if (idx != -1 && ((idx+1) < apkName.length())) {
5550 // Make sure the package ends with a numeral
5551 String version = apkName.substring(idx+1);
5552 try {
5553 Integer.parseInt(version);
5554 return true;
5555 } catch (NumberFormatException e) {}
5556 }
5557 return false;
5558 }
5559
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005560 // Utility method that returns the relative package path with respect
5561 // to the installation directory. Like say for /data/data/com.test-1.apk
5562 // string com.test-1 is returned.
5563 static String getApkName(String codePath) {
5564 if (codePath == null) {
5565 return null;
5566 }
5567 int sidx = codePath.lastIndexOf("/");
5568 int eidx = codePath.lastIndexOf(".");
5569 if (eidx == -1) {
5570 eidx = codePath.length();
5571 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005572 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005573 return null;
5574 }
5575 return codePath.substring(sidx+1, eidx);
5576 }
5577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 class PackageInstalledInfo {
5579 String name;
5580 int uid;
5581 PackageParser.Package pkg;
5582 int returnCode;
5583 PackageRemovedInfo removedInfo;
5584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 /*
5587 * Install a non-existing package.
5588 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005589 private void installNewPackageLI(PackageParser.Package pkg,
5590 int parseFlags,
5591 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005592 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005594 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005595
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08005596 boolean dataDirExists = getDataPathForPackage(pkg).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 res.name = pkgName;
5598 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07005599 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
5600 // A package with the same name is already installed, though
5601 // it has been renamed to an older name. The package we
5602 // are trying to install should be installed as an update to
5603 // the existing one, but that has not been requested, so bail.
5604 Slog.w(TAG, "Attempt to re-install " + pkgName
5605 + " without first uninstalling package running as "
5606 + mSettings.mRenamedPackages.get(pkgName));
5607 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5608 return;
5609 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005610 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005612 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005613 + " without first uninstalling.");
5614 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5615 return;
5616 }
5617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005618 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005619 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
5620 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005622 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5624 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5625 }
5626 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005627 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005628 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 res);
5630 // delete the partially installed application. the data directory will have to be
5631 // restored if it was already existing
5632 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5633 // remove package from internal structures. Note that we want deletePackageX to
5634 // delete the package data and cache directories that it created in
5635 // scanPackageLocked, unless those directories existed before we even tried to
5636 // install.
5637 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005638 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005640 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 }
5642 }
5643 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005644
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005645 private void replacePackageLI(PackageParser.Package pkg,
5646 int parseFlags,
5647 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005648 String installerPackageName, PackageInstalledInfo res) {
5649
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005650 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005651 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 // First find the old package info and check signatures
5653 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005654 oldPackage = mPackages.get(pkgName);
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005655 if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005656 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5658 return;
5659 }
5660 }
Kenny Root85387d72010-08-26 10:13:11 -07005661 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005662 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005663 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005664 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005665 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 }
5667 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005670 PackageParser.Package pkg,
5671 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005672 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 PackageParser.Package newPackage = null;
5674 String pkgName = deletedPackage.packageName;
5675 boolean deletedPkg = true;
5676 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005677
Jacek Surazski65e13172009-04-28 15:26:38 +02005678 String oldInstallerPackageName = null;
5679 synchronized (mPackages) {
5680 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
5681 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005682
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005683 long origUpdateTime;
5684 if (pkg.mExtras != null) {
5685 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
5686 } else {
5687 origUpdateTime = 0;
5688 }
5689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005690 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005691 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005692 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005693 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5695 deletedPkg = false;
5696 } else {
5697 // Successfully deleted the old package. Now proceed with re-installation
5698 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005699 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
5700 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005702 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005703 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5704 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005705 }
5706 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005707 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005708 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 res);
5710 updatedSettings = true;
5711 }
5712 }
5713
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005714 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 // remove package from internal structures. Note that we want deletePackageX to
5716 // delete the package data and cache directories that it created in
5717 // scanPackageLocked, unless those directories existed before we even tried to
5718 // install.
5719 if(updatedSettings) {
5720 deletePackageLI(
5721 pkgName, true,
5722 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005723 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005724 }
5725 // Since we failed to install the new package we need to restore the old
5726 // package that we deleted.
5727 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005728 File restoreFile = new File(deletedPackage.mPath);
5729 if (restoreFile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005730 Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005731 return;
5732 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005733 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005734 boolean oldOnSd = isExternal(deletedPackage);
5735 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
5736 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5737 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005738 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
5739 | SCAN_UPDATE_TIME;
5740 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
5741 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005742 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
5743 return;
5744 }
5745 // Restore of old package succeeded. Update permissions.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005746 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005747 updatePermissionsLP(deletedPackage.packageName, deletedPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07005748 true, false, false);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005749 mSettings.writeLP();
5750 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005751 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752 }
5753 }
5754 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005756 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005757 PackageParser.Package pkg,
5758 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005759 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 PackageParser.Package newPackage = null;
5761 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005762 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005763 PackageParser.PARSE_IS_SYSTEM;
5764 String packageName = deletedPackage.packageName;
5765 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5766 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005767 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 return;
5769 }
5770 PackageParser.Package oldPkg;
5771 PackageSetting oldPkgSetting;
5772 synchronized (mPackages) {
5773 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005774 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005775 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5776 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005777 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005778 return;
5779 }
5780 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005781
5782 killApplication(packageName, oldPkg.applicationInfo.uid);
5783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5785 res.removedInfo.removedPackage = packageName;
5786 // Remove existing system package
5787 removePackageLI(oldPkg, true);
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005788 synchronized (mPackages) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005789 if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) {
5790 // We didn't need to disable the .apk as a current system package,
5791 // which means we are replacing another update that is already
5792 // installed. We need to make sure to delete the older one's .apk.
5793 res.removedInfo.args = createInstallArgs(isExternal(pkg)
5794 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
5795 deletedPackage.applicationInfo.sourceDir,
5796 deletedPackage.applicationInfo.publicSourceDir,
5797 deletedPackage.applicationInfo.nativeLibraryDir);
5798 } else {
5799 res.removedInfo.args = null;
5800 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005801 }
5802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 // Successfully disabled the old package. Now proceed with re-installation
5804 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5805 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005806 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005808 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5810 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5811 }
5812 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005813 if (newPackage.mExtras != null) {
5814 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
5815 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
5816 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
5817 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005818 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005819 updatedSettings = true;
5820 }
5821
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005822 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 // Re installation failed. Restore old information
5824 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005825 if (newPackage != null) {
5826 removePackageLI(newPackage, true);
5827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005829 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 // Restore the old system information in Settings
5831 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005832 if (updatedSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005834 mSettings.setInstallerPackageName(packageName,
5835 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 }
5837 mSettings.writeLP();
5838 }
5839 }
5840 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005841
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005842 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005843 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005844 int retCode;
5845 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5846 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5847 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07005848 if (mNoDexOpt) {
5849 /*
5850 * If we're in an engineering build, programs are lazily run
5851 * through dexopt. If the .dex file doesn't exist yet, it
5852 * will be created when the program is run next.
5853 */
5854 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
5855 } else {
5856 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
5857 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5858 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005859 }
5860 }
5861 return PackageManager.INSTALL_SUCCEEDED;
5862 }
5863
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005864 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005865 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005866 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 synchronized (mPackages) {
5868 //write settings. the installStatus will be incomplete at this stage.
5869 //note that the new package setting would have already been
5870 //added to mPackages. It hasn't been persisted yet.
5871 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5872 mSettings.writeLP();
5873 }
5874
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005875 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005876 != PackageManager.INSTALL_SUCCEEDED) {
5877 // Discontinue if moving dex files failed.
5878 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005880 if((res.returnCode = setPermissionsLI(newPackage))
5881 != PackageManager.INSTALL_SUCCEEDED) {
5882 if (mInstaller != null) {
5883 mInstaller.rmdex(newPackage.mScanPath);
5884 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005885 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005887 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005890 updatePermissionsLP(newPackage.packageName, newPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07005891 newPackage.permissions.size() > 0, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 res.name = pkgName;
5893 res.uid = newPackage.applicationInfo.uid;
5894 res.pkg = newPackage;
5895 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005896 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5898 //to update install status
5899 mSettings.writeLP();
5900 }
5901 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005902
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005903 private void installPackageLI(InstallArgs args,
5904 boolean newInstall, PackageInstalledInfo res) {
5905 int pFlags = args.flags;
5906 String installerPackageName = args.installerPackageName;
5907 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005908 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005909 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005910 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005911 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005912 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005913 // Result object to be returned
5914 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5915
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005916 // Retrieve PackageSettings and parse package
5917 int parseFlags = PackageParser.PARSE_CHATTY |
5918 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5919 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5920 parseFlags |= mDefParseFlags;
5921 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5922 pp.setSeparateProcesses(mSeparateProcesses);
5923 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5924 null, mMetrics, parseFlags);
5925 if (pkg == null) {
5926 res.returnCode = pp.getParseError();
5927 return;
5928 }
5929 String pkgName = res.name = pkg.packageName;
5930 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5931 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5932 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5933 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005935 }
5936 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5937 res.returnCode = pp.getParseError();
5938 return;
5939 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005940 // Get rid of all references to package scan path via parser.
5941 pp = null;
5942 String oldCodePath = null;
5943 boolean systemApp = false;
5944 synchronized (mPackages) {
5945 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005946 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5947 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08005948 if (pkg.mOriginalPackages != null
5949 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005950 && mPackages.containsKey(oldName)) {
5951 // This package is derived from an original package,
5952 // and this device has been updating from that original
5953 // name. We must continue using the original name, so
5954 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08005955 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005956 pkgName = pkg.packageName;
5957 replace = true;
5958 } else if (mPackages.containsKey(pkgName)) {
5959 // This package, under its official name, already exists
5960 // on the device; we should replace it.
5961 replace = true;
5962 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005963 }
5964 PackageSetting ps = mSettings.mPackages.get(pkgName);
5965 if (ps != null) {
5966 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5967 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5968 systemApp = (ps.pkg.applicationInfo.flags &
5969 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005970 }
5971 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005972 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005973
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005974 if (systemApp && onSd) {
5975 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005976 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005977 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5978 return;
5979 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08005980
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005981 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5982 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5983 return;
5984 }
5985 // Set application objects path explicitly after the rename
5986 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07005987 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005988 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005989 replacePackageLI(pkg, parseFlags, scanMode,
5990 installerPackageName, res);
5991 } else {
5992 installNewPackageLI(pkg, parseFlags, scanMode,
5993 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 }
5995 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005996
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005997 private int setPermissionsLI(PackageParser.Package newPackage) {
5998 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005999 int retCode = 0;
6000 // TODO Gross hack but fix later. Ideally move this to be a post installation
6001 // check after alloting uid.
Kenny Root85387d72010-08-26 10:13:11 -07006002 if (isForwardLocked(newPackage)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006003 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 try {
6005 extractPublicFiles(newPackage, destResourceFile);
6006 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006007 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 -08006008 " forward-locked app.");
6009 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6010 } finally {
6011 //TODO clean up the extracted public files
6012 }
6013 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006014 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 newPackage.applicationInfo.uid);
6016 } else {
6017 final int filePermissions =
6018 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006019 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 newPackage.applicationInfo.uid);
6021 }
6022 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006023 // The permissions on the resource file was set when it was copied for
6024 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006028 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006029 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006031 // TODO Define new internal error
6032 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006033 }
6034 return PackageManager.INSTALL_SUCCEEDED;
6035 }
6036
Kenny Root85387d72010-08-26 10:13:11 -07006037 private static boolean isForwardLocked(PackageParser.Package pkg) {
6038 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 }
6040
Kenny Root85387d72010-08-26 10:13:11 -07006041 private static boolean isExternal(PackageParser.Package pkg) {
6042 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
6043 }
6044
6045 private static boolean isSystemApp(PackageParser.Package pkg) {
6046 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6047 }
6048
Kenny Root502e9a42011-01-10 13:48:15 -08006049 private static boolean isSystemApp(ApplicationInfo info) {
6050 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6051 }
6052
Kenny Root85387d72010-08-26 10:13:11 -07006053 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
6054 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006055 }
6056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006057 private void extractPublicFiles(PackageParser.Package newPackage,
6058 File publicZipFile) throws IOException {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006059 final FileOutputStream fstr = new FileOutputStream(publicZipFile);
6060 final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 final ZipFile privateZip = new ZipFile(newPackage.mPath);
6062
6063 // Copy manifest, resources.arsc and res directory to public zip
6064
6065 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
6066 while (privateZipEntries.hasMoreElements()) {
6067 final ZipEntry zipEntry = privateZipEntries.nextElement();
6068 final String zipEntryName = zipEntry.getName();
6069 if ("AndroidManifest.xml".equals(zipEntryName)
6070 || "resources.arsc".equals(zipEntryName)
6071 || zipEntryName.startsWith("res/")) {
6072 try {
6073 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
6074 } catch (IOException e) {
6075 try {
6076 publicZipOutStream.close();
6077 throw e;
6078 } finally {
6079 publicZipFile.delete();
6080 }
6081 }
6082 }
6083 }
6084
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006085 publicZipOutStream.finish();
6086 publicZipOutStream.flush();
6087 FileUtils.sync(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006088 publicZipOutStream.close();
6089 FileUtils.setPermissions(
6090 publicZipFile.getAbsolutePath(),
6091 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
6092 -1, -1);
6093 }
6094
6095 private static void copyZipEntry(ZipEntry zipEntry,
6096 ZipFile inZipFile,
6097 ZipOutputStream outZipStream) throws IOException {
6098 byte[] buffer = new byte[4096];
6099 int num;
6100
6101 ZipEntry newEntry;
6102 if (zipEntry.getMethod() == ZipEntry.STORED) {
6103 // Preserve the STORED method of the input entry.
6104 newEntry = new ZipEntry(zipEntry);
6105 } else {
6106 // Create a new entry so that the compressed len is recomputed.
6107 newEntry = new ZipEntry(zipEntry.getName());
6108 }
6109 outZipStream.putNextEntry(newEntry);
6110
6111 InputStream data = inZipFile.getInputStream(zipEntry);
6112 while ((num = data.read(buffer)) > 0) {
6113 outZipStream.write(buffer, 0, num);
6114 }
6115 outZipStream.flush();
6116 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 private void deleteTempPackageFiles() {
6119 FilenameFilter filter = new FilenameFilter() {
6120 public boolean accept(File dir, String name) {
6121 return name.startsWith("vmdl") && name.endsWith(".tmp");
6122 }
6123 };
6124 String tmpFilesList[] = mAppInstallDir.list(filter);
6125 if(tmpFilesList == null) {
6126 return;
6127 }
6128 for(int i = 0; i < tmpFilesList.length; i++) {
6129 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
6130 tmpFile.delete();
6131 }
6132 }
6133
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006134 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 File tmpPackageFile;
6136 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006137 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006138 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006139 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 return null;
6141 }
6142 try {
6143 FileUtils.setPermissions(
6144 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
6145 -1, -1);
6146 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006147 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 return null;
6149 }
6150 return tmpPackageFile;
6151 }
6152
6153 public void deletePackage(final String packageName,
6154 final IPackageDeleteObserver observer,
6155 final int flags) {
6156 mContext.enforceCallingOrSelfPermission(
6157 android.Manifest.permission.DELETE_PACKAGES, null);
6158 // Queue up an async operation since the package deletion may take a little while.
6159 mHandler.post(new Runnable() {
6160 public void run() {
6161 mHandler.removeCallbacks(this);
6162 final boolean succeded = deletePackageX(packageName, true, true, flags);
6163 if (observer != null) {
6164 try {
6165 observer.packageDeleted(succeded);
6166 } catch (RemoteException e) {
6167 Log.i(TAG, "Observer no longer exists.");
6168 } //end catch
6169 } //end if
6170 } //end run
6171 });
6172 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006174 /**
6175 * This method is an internal method that could be get invoked either
6176 * to delete an installed package or to clean up a failed installation.
6177 * After deleting an installed package, a broadcast is sent to notify any
6178 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006179 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 * installation wouldn't have sent the initial broadcast either
6181 * The key steps in deleting a package are
6182 * deleting the package information in internal structures like mPackages,
6183 * deleting the packages base directories through installd
6184 * updating mSettings to reflect current status
6185 * persisting settings for later use
6186 * sending a broadcast if necessary
6187 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 private boolean deletePackageX(String packageName, boolean sendBroadCast,
6189 boolean deleteCodeAndResources, int flags) {
6190 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07006191 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006193 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
6194 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
6195 try {
6196 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006197 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006198 return false;
6199 }
6200 } catch (RemoteException e) {
6201 }
6202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006204 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006205 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07006209 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006210 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07006211
6212 // If the removed package was a system update, the old system packaged
6213 // was re-enabled; we need to broadcast this information
6214 if (systemUpdate) {
6215 Bundle extras = new Bundle(1);
6216 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
6217 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6218
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006219 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null);
6220 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null);
Romain Guy96f43572009-03-24 20:27:49 -07006221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006222 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006223 // Force a gc here.
6224 Runtime.getRuntime().gc();
6225 // Delete the resources here after sending the broadcast to let
6226 // other processes clean up before deleting resources.
6227 if (info.args != null) {
6228 synchronized (mInstallLock) {
6229 info.args.doPostDeleteLI(deleteCodeAndResources);
6230 }
6231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 return res;
6233 }
6234
6235 static class PackageRemovedInfo {
6236 String removedPackage;
6237 int uid = -1;
6238 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07006239 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006240 // Clean up resources deleted packages.
6241 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07006242
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006243 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006244 Bundle extras = new Bundle(1);
6245 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
6246 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
6247 if (replacing) {
6248 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6249 }
6250 if (removedPackage != null) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006251 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006252 }
6253 if (removedUid >= 0) {
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006254 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 }
6256 }
6257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 /*
6260 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
6261 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006262 * 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 -08006263 * delete a partially installed application.
6264 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006265 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006266 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006268 if (outInfo != null) {
6269 outInfo.removedPackage = packageName;
6270 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006271 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006272 // Retrieve object to delete permissions for shared user later on
6273 PackageSetting deletedPs;
6274 synchronized (mPackages) {
6275 deletedPs = mSettings.mPackages.get(packageName);
6276 }
6277 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6278 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06006279 int retCode = mInstaller.remove(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006280 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006281 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006282 + packageName + ", retcode=" + retCode);
6283 // we don't consider this to be a failure of the core package deletion
6284 }
6285 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006286 // for simulator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 PackageParser.Package pkg = mPackages.get(packageName);
6288 File dataDir = new File(pkg.applicationInfo.dataDir);
6289 dataDir.delete();
6290 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07006291 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 }
6293 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006294 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006295 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6296 if (outInfo != null) {
6297 outInfo.removedUid = mSettings.removePackageLP(packageName);
6298 }
6299 if (deletedPs != null) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07006300 updatePermissionsLP(deletedPs.name, null, false, false, false);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006301 if (deletedPs.sharedUser != null) {
6302 // remove permissions associated with package
6303 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
6304 }
6305 }
6306 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006307 // remove from preferred activities.
6308 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
6309 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
6310 if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
6311 removed.add(pa);
6312 }
6313 }
6314 for (PreferredActivity pa : removed) {
6315 mSettings.mPreferredActivities.removeFilter(pa);
6316 }
6317 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006318 if (writeSettings) {
6319 // Save settings now
6320 mSettings.writeLP();
6321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 }
6323 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 /*
6326 * Tries to delete system package.
6327 */
6328 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006329 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 ApplicationInfo applicationInfo = p.applicationInfo;
6331 //applicable for non-partially installed applications only
6332 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006333 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 return false;
6335 }
6336 PackageSetting ps = null;
6337 // Confirm if the system package has been updated
6338 // An updated system app can be deleted. This will also have to restore
6339 // the system pkg from system partition
6340 synchronized (mPackages) {
6341 ps = mSettings.getDisabledSystemPkg(p.packageName);
6342 }
6343 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006344 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006345 return false;
6346 } else {
6347 Log.i(TAG, "Deleting system pkg from data partition");
6348 }
6349 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07006350 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006351 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006352 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006353 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006354 } else {
6355 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006356 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006357 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006358 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006359 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006360 if (!ret) {
6361 return false;
6362 }
6363 synchronized (mPackages) {
6364 // Reinstate the old system package
6365 mSettings.enableSystemPackageLP(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07006366 // Remove any native libraries from the upgraded package.
6367 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006368 }
6369 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006370 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006372 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006375 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006376 return false;
6377 }
6378 synchronized (mPackages) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07006379 updatePermissionsLP(newPkg.packageName, newPkg, true, true, false);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006380 if (writeSettings) {
6381 mSettings.writeLP();
6382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 }
6384 return true;
6385 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006387 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006388 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6389 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006390 ApplicationInfo applicationInfo = p.applicationInfo;
6391 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006392 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 return false;
6394 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006395 if (outInfo != null) {
6396 outInfo.uid = applicationInfo.uid;
6397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398
6399 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006400 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401
6402 // Delete application code and resources
6403 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006404 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07006405 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
6406 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
6407 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
6408 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006409 }
6410 return true;
6411 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 /*
6414 * This method handles package deletion in general
6415 */
6416 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006417 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6418 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006420 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 return false;
6422 }
6423 PackageParser.Package p;
6424 boolean dataOnly = false;
6425 synchronized (mPackages) {
6426 p = mPackages.get(packageName);
6427 if (p == null) {
6428 //this retrieves partially installed apps
6429 dataOnly = true;
6430 PackageSetting ps = mSettings.mPackages.get(packageName);
6431 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006432 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 return false;
6434 }
6435 p = ps.pkg;
6436 }
6437 }
6438 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006439 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 return false;
6441 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 if (dataOnly) {
6444 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006445 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 return true;
6447 }
6448 // At this point the package should have ApplicationInfo associated with it
6449 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006450 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 return false;
6452 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006453 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07006454 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 Log.i(TAG, "Removing system package:"+p.packageName);
6456 // When an updated system application is deleted we delete the existing resources as well and
6457 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006458 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006459 } else {
6460 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006461 // Kill application pre-emptively especially for apps on sd.
6462 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006463 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
6464 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006466 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 public void clearApplicationUserData(final String packageName,
6470 final IPackageDataObserver observer) {
6471 mContext.enforceCallingOrSelfPermission(
6472 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
6473 // Queue up an async operation since the package deletion may take a little while.
6474 mHandler.post(new Runnable() {
6475 public void run() {
6476 mHandler.removeCallbacks(this);
6477 final boolean succeeded;
6478 synchronized (mInstallLock) {
6479 succeeded = clearApplicationUserDataLI(packageName);
6480 }
6481 if (succeeded) {
6482 // invoke DeviceStorageMonitor's update method to clear any notifications
6483 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
6484 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
6485 if (dsm != null) {
6486 dsm.updateMemory();
6487 }
6488 }
6489 if(observer != null) {
6490 try {
6491 observer.onRemoveCompleted(packageName, succeeded);
6492 } catch (RemoteException e) {
6493 Log.i(TAG, "Observer no longer exists.");
6494 }
6495 } //end if observer
6496 } //end run
6497 });
6498 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500 private boolean clearApplicationUserDataLI(String packageName) {
6501 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006502 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 return false;
6504 }
6505 PackageParser.Package p;
6506 boolean dataOnly = false;
6507 synchronized (mPackages) {
6508 p = mPackages.get(packageName);
6509 if(p == null) {
6510 dataOnly = true;
6511 PackageSetting ps = mSettings.mPackages.get(packageName);
6512 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006513 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 return false;
6515 }
6516 p = ps.pkg;
6517 }
6518 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006519 boolean useEncryptedFSDir = false;
6520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 if(!dataOnly) {
6522 //need to check this only for fully installed applications
6523 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006524 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 return false;
6526 }
6527 final ApplicationInfo applicationInfo = p.applicationInfo;
6528 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006529 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 return false;
6531 }
6532 }
6533 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06006534 int retCode = mInstaller.clearUserData(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006536 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 + packageName);
6538 return false;
6539 }
6540 }
6541 return true;
6542 }
6543
6544 public void deleteApplicationCacheFiles(final String packageName,
6545 final IPackageDataObserver observer) {
6546 mContext.enforceCallingOrSelfPermission(
6547 android.Manifest.permission.DELETE_CACHE_FILES, null);
6548 // Queue up an async operation since the package deletion may take a little while.
6549 mHandler.post(new Runnable() {
6550 public void run() {
6551 mHandler.removeCallbacks(this);
6552 final boolean succeded;
6553 synchronized (mInstallLock) {
6554 succeded = deleteApplicationCacheFilesLI(packageName);
6555 }
6556 if(observer != null) {
6557 try {
6558 observer.onRemoveCompleted(packageName, succeded);
6559 } catch (RemoteException e) {
6560 Log.i(TAG, "Observer no longer exists.");
6561 }
6562 } //end if observer
6563 } //end run
6564 });
6565 }
6566
6567 private boolean deleteApplicationCacheFilesLI(String packageName) {
6568 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006569 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006570 return false;
6571 }
6572 PackageParser.Package p;
6573 synchronized (mPackages) {
6574 p = mPackages.get(packageName);
6575 }
6576 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006577 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006578 return false;
6579 }
6580 final ApplicationInfo applicationInfo = p.applicationInfo;
6581 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006582 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 return false;
6584 }
6585 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06006586 int retCode = mInstaller.deleteCacheFiles(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006588 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006589 + packageName);
6590 return false;
6591 }
6592 }
6593 return true;
6594 }
6595
6596 public void getPackageSizeInfo(final String packageName,
6597 final IPackageStatsObserver observer) {
6598 mContext.enforceCallingOrSelfPermission(
6599 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6600 // Queue up an async operation since the package deletion may take a little while.
6601 mHandler.post(new Runnable() {
6602 public void run() {
6603 mHandler.removeCallbacks(this);
6604 PackageStats lStats = new PackageStats(packageName);
6605 final boolean succeded;
6606 synchronized (mInstallLock) {
6607 succeded = getPackageSizeInfoLI(packageName, lStats);
6608 }
6609 if(observer != null) {
6610 try {
6611 observer.onGetStatsCompleted(lStats, succeded);
6612 } catch (RemoteException e) {
6613 Log.i(TAG, "Observer no longer exists.");
6614 }
6615 } //end if observer
6616 } //end run
6617 });
6618 }
6619
6620 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6621 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006622 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006623 return false;
6624 }
6625 PackageParser.Package p;
6626 boolean dataOnly = false;
6627 synchronized (mPackages) {
6628 p = mPackages.get(packageName);
6629 if(p == null) {
6630 dataOnly = true;
6631 PackageSetting ps = mSettings.mPackages.get(packageName);
6632 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006633 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006634 return false;
6635 }
6636 p = ps.pkg;
6637 }
6638 }
6639 String publicSrcDir = null;
6640 if(!dataOnly) {
6641 final ApplicationInfo applicationInfo = p.applicationInfo;
6642 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006643 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006644 return false;
6645 }
6646 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6647 }
6648 if (mInstaller != null) {
Jason parks1125d782011-01-12 09:47:26 -06006649 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006650 if (res < 0) {
6651 return false;
6652 } else {
6653 return true;
6654 }
6655 }
6656 return true;
6657 }
6658
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006661 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 }
6663
6664 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006665 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006666 }
6667
6668 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006669 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 }
6671
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006672 int getUidTargetSdkVersionLockedLP(int uid) {
6673 Object obj = mSettings.getUserIdLP(uid);
6674 if (obj instanceof SharedUserSetting) {
6675 SharedUserSetting sus = (SharedUserSetting)obj;
6676 final int N = sus.packages.size();
6677 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
6678 Iterator<PackageSetting> it = sus.packages.iterator();
6679 int i=0;
6680 while (it.hasNext()) {
6681 PackageSetting ps = it.next();
6682 if (ps.pkg != null) {
6683 int v = ps.pkg.applicationInfo.targetSdkVersion;
6684 if (v < vers) vers = v;
6685 }
6686 }
6687 return vers;
6688 } else if (obj instanceof PackageSetting) {
6689 PackageSetting ps = (PackageSetting)obj;
6690 if (ps.pkg != null) {
6691 return ps.pkg.applicationInfo.targetSdkVersion;
6692 }
6693 }
6694 return Build.VERSION_CODES.CUR_DEVELOPMENT;
6695 }
6696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 public void addPreferredActivity(IntentFilter filter, int match,
6698 ComponentName[] set, ComponentName activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006700 if (mContext.checkCallingOrSelfPermission(
6701 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6702 != PackageManager.PERMISSION_GRANTED) {
6703 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6704 < Build.VERSION_CODES.FROYO) {
6705 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
6706 + Binder.getCallingUid());
6707 return;
6708 }
6709 mContext.enforceCallingOrSelfPermission(
6710 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6711 }
6712
6713 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6715 mSettings.mPreferredActivities.addFilter(
6716 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006717 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 }
6719 }
6720
Satish Sampath8dbe6122009-06-02 23:35:54 +01006721 public void replacePreferredActivity(IntentFilter filter, int match,
6722 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01006723 if (filter.countActions() != 1) {
6724 throw new IllegalArgumentException(
6725 "replacePreferredActivity expects filter to have only 1 action.");
6726 }
6727 if (filter.countCategories() != 1) {
6728 throw new IllegalArgumentException(
6729 "replacePreferredActivity expects filter to have only 1 category.");
6730 }
6731 if (filter.countDataAuthorities() != 0
6732 || filter.countDataPaths() != 0
6733 || filter.countDataSchemes() != 0
6734 || filter.countDataTypes() != 0) {
6735 throw new IllegalArgumentException(
6736 "replacePreferredActivity expects filter to have no data authorities, " +
6737 "paths, schemes or types.");
6738 }
6739 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006740 if (mContext.checkCallingOrSelfPermission(
6741 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6742 != PackageManager.PERMISSION_GRANTED) {
6743 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6744 < Build.VERSION_CODES.FROYO) {
6745 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
6746 + Binder.getCallingUid());
6747 return;
6748 }
6749 mContext.enforceCallingOrSelfPermission(
6750 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6751 }
6752
Satish Sampath8dbe6122009-06-02 23:35:54 +01006753 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6754 String action = filter.getAction(0);
6755 String category = filter.getCategory(0);
6756 while (it.hasNext()) {
6757 PreferredActivity pa = it.next();
6758 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6759 it.remove();
6760 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
6761 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6762 }
6763 }
6764 addPreferredActivity(filter, match, set, activity);
6765 }
6766 }
6767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 public void clearPackagePreferredActivities(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006770 int uid = Binder.getCallingUid();
6771 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006772 if (pkg == null || pkg.applicationInfo.uid != uid) {
6773 if (mContext.checkCallingOrSelfPermission(
6774 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6775 != PackageManager.PERMISSION_GRANTED) {
6776 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6777 < Build.VERSION_CODES.FROYO) {
6778 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
6779 + Binder.getCallingUid());
6780 return;
6781 }
6782 mContext.enforceCallingOrSelfPermission(
6783 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6784 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006785 }
6786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 if (clearPackagePreferredActivitiesLP(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006788 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 }
6790 }
6791 }
6792
6793 boolean clearPackagePreferredActivitiesLP(String packageName) {
6794 boolean changed = false;
6795 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6796 while (it.hasNext()) {
6797 PreferredActivity pa = it.next();
6798 if (pa.mActivity.getPackageName().equals(packageName)) {
6799 it.remove();
6800 changed = true;
6801 }
6802 }
6803 return changed;
6804 }
6805
6806 public int getPreferredActivities(List<IntentFilter> outFilters,
6807 List<ComponentName> outActivities, String packageName) {
6808
6809 int num = 0;
6810 synchronized (mPackages) {
6811 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6812 while (it.hasNext()) {
6813 PreferredActivity pa = it.next();
6814 if (packageName == null
6815 || pa.mActivity.getPackageName().equals(packageName)) {
6816 if (outFilters != null) {
6817 outFilters.add(new IntentFilter(pa));
6818 }
6819 if (outActivities != null) {
6820 outActivities.add(pa.mActivity);
6821 }
6822 }
6823 }
6824 }
6825
6826 return num;
6827 }
6828
6829 public void setApplicationEnabledSetting(String appPackageName,
6830 int newState, int flags) {
6831 setEnabledSetting(appPackageName, null, newState, flags);
6832 }
6833
6834 public void setComponentEnabledSetting(ComponentName componentName,
6835 int newState, int flags) {
6836 setEnabledSetting(componentName.getPackageName(),
6837 componentName.getClassName(), newState, flags);
6838 }
6839
6840 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006841 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
6843 || newState == COMPONENT_ENABLED_STATE_ENABLED
6844 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
6845 throw new IllegalArgumentException("Invalid new component state: "
6846 + newState);
6847 }
6848 PackageSetting pkgSetting;
6849 final int uid = Binder.getCallingUid();
6850 final int permission = mContext.checkCallingPermission(
6851 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
6852 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006853 boolean sendNow = false;
6854 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006855 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006856 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006857 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006858 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006859 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006860 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006861 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006863 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006864 }
6865 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006866 "Unknown component: " + packageName
6867 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006868 }
6869 if (!allowedByPermission && (uid != pkgSetting.userId)) {
6870 throw new SecurityException(
6871 "Permission Denial: attempt to change component state from pid="
6872 + Binder.getCallingPid()
6873 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
6874 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006875 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006876 // We're dealing with an application/package level state change
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006877 if (pkgSetting.enabled == newState) {
6878 // Nothing to do
6879 return;
6880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 pkgSetting.enabled = newState;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07006882 pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 } else {
6884 // We're dealing with a component level state change
6885 switch (newState) {
6886 case COMPONENT_ENABLED_STATE_ENABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006887 if (!pkgSetting.enableComponentLP(className)) {
6888 return;
6889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 break;
6891 case COMPONENT_ENABLED_STATE_DISABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006892 if (!pkgSetting.disableComponentLP(className)) {
6893 return;
6894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006895 break;
6896 case COMPONENT_ENABLED_STATE_DEFAULT:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006897 if (!pkgSetting.restoreComponentLP(className)) {
6898 return;
6899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 break;
6901 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006902 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006903 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006904 }
6905 }
6906 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006907 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006908 components = mPendingBroadcasts.get(packageName);
6909 boolean newPackage = components == null;
6910 if (newPackage) {
6911 components = new ArrayList<String>();
6912 }
6913 if (!components.contains(componentName)) {
6914 components.add(componentName);
6915 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006916 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6917 sendNow = true;
6918 // Purge entry from pending broadcast list if another one exists already
6919 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006920 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006921 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006922 if (newPackage) {
6923 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006924 }
6925 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6926 // Schedule a message
6927 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6928 }
6929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006932 long callingId = Binder.clearCallingIdentity();
6933 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006934 if (sendNow) {
6935 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006936 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006938 } finally {
6939 Binder.restoreCallingIdentity(callingId);
6940 }
6941 }
6942
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006943 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006944 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6945 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6946 + " components=" + componentNames);
6947 Bundle extras = new Bundle(4);
6948 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6949 String nameList[] = new String[componentNames.size()];
6950 componentNames.toArray(nameList);
6951 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006952 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
6953 extras.putInt(Intent.EXTRA_UID, packageUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07006954 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006955 }
6956
Jacek Surazski65e13172009-04-28 15:26:38 +02006957 public String getInstallerPackageName(String packageName) {
6958 synchronized (mPackages) {
6959 PackageSetting pkg = mSettings.mPackages.get(packageName);
6960 if (pkg == null) {
6961 throw new IllegalArgumentException("Unknown package: " + packageName);
6962 }
6963 return pkg.installerPackageName;
6964 }
6965 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006967 public int getApplicationEnabledSetting(String appPackageName) {
6968 synchronized (mPackages) {
6969 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
6970 if (pkg == null) {
6971 throw new IllegalArgumentException("Unknown package: " + appPackageName);
6972 }
6973 return pkg.enabled;
6974 }
6975 }
6976
6977 public int getComponentEnabledSetting(ComponentName componentName) {
6978 synchronized (mPackages) {
6979 final String packageNameStr = componentName.getPackageName();
6980 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
6981 if (pkg == null) {
6982 throw new IllegalArgumentException("Unknown component: " + componentName);
6983 }
6984 final String classNameStr = componentName.getClassName();
6985 return pkg.currentEnabledStateLP(classNameStr);
6986 }
6987 }
6988
6989 public void enterSafeMode() {
6990 if (!mSystemReady) {
6991 mSafeMode = true;
6992 }
6993 }
6994
6995 public void systemReady() {
6996 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006997
6998 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006999 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007000 mContext.getContentResolver(),
7001 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007002 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007003 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007004 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 }
7007
7008 public boolean isSafeMode() {
7009 return mSafeMode;
7010 }
7011
7012 public boolean hasSystemUidErrors() {
7013 return mHasSystemUidErrors;
7014 }
7015
7016 static String arrayToString(int[] array) {
7017 StringBuffer buf = new StringBuffer(128);
7018 buf.append('[');
7019 if (array != null) {
7020 for (int i=0; i<array.length; i++) {
7021 if (i > 0) buf.append(", ");
7022 buf.append(array[i]);
7023 }
7024 }
7025 buf.append(']');
7026 return buf.toString();
7027 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 @Override
7030 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7031 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
7032 != PackageManager.PERMISSION_GRANTED) {
7033 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7034 + Binder.getCallingPid()
7035 + ", uid=" + Binder.getCallingUid()
7036 + " without permission "
7037 + android.Manifest.permission.DUMP);
7038 return;
7039 }
7040
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007041 boolean dumpStar = true;
7042 boolean dumpLibs = false;
7043 boolean dumpFeatures = false;
7044 boolean dumpResolvers = false;
7045 boolean dumpPermissions = false;
7046 boolean dumpPackages = false;
7047 boolean dumpSharedUsers = false;
7048 boolean dumpMessages = false;
7049 boolean dumpProviders = false;
7050
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007051 String packageName = null;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007052 boolean showFilters = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007053
7054 int opti = 0;
7055 while (opti < args.length) {
7056 String opt = args[opti];
7057 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7058 break;
7059 }
7060 opti++;
7061 if ("-a".equals(opt)) {
7062 // Right now we only know how to print all.
7063 } else if ("-h".equals(opt)) {
7064 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007065 pw.println(" [-h] [-f] [cmd] ...");
7066 pw.println(" -f: print details of intent filters");
7067 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007068 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007069 pw.println(" l[ibraries]: list known shared libraries");
7070 pw.println(" f[ibraries]: list device features");
7071 pw.println(" r[esolvers]: dump intent resolvers");
7072 pw.println(" perm[issions]: dump permissions");
7073 pw.println(" prov[iders]: dump content providers");
7074 pw.println(" p[ackages]: dump installed packages");
7075 pw.println(" s[hared-users]: dump shared user IDs");
7076 pw.println(" m[essages]: print collected runtime messages");
7077 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007078 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007079 } else if ("-f".equals(opt)) {
7080 showFilters = true;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007081 } else {
7082 pw.println("Unknown argument: " + opt + "; use -h for help");
7083 }
7084 }
7085
7086 // Is the caller requesting to dump a particular piece of data?
7087 if (opti < args.length) {
7088 String cmd = args[opti];
7089 opti++;
7090 // Is this a package name?
7091 if ("android".equals(cmd) || cmd.contains(".")) {
7092 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007093 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
7094 dumpStar = false;
7095 dumpLibs = true;
7096 } else if ("f".equals(cmd) || "features".equals(cmd)) {
7097 dumpStar = false;
7098 dumpFeatures = true;
7099 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
7100 dumpStar = false;
7101 dumpResolvers = true;
7102 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
7103 dumpStar = false;
7104 dumpPermissions = true;
7105 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
7106 dumpStar = false;
7107 dumpPackages = true;
7108 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
7109 dumpStar = false;
7110 dumpSharedUsers = true;
7111 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
7112 dumpStar = false;
7113 dumpProviders = true;
7114 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
7115 dumpStar = false;
7116 dumpMessages = true;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007117 }
7118 }
7119
7120 boolean printedTitle = false;
7121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007122 synchronized (mPackages) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007123 if ((dumpStar || dumpLibs) && packageName == null) {
7124 if (printedTitle) pw.println(" ");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007125 printedTitle = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007126 pw.println("Libraries:");
7127 Iterator<String> it = mSharedLibraries.keySet().iterator();
7128 while (it.hasNext()) {
7129 String name = it.next();
7130 pw.print(" ");
7131 pw.print(name);
7132 pw.print(" -> ");
7133 pw.println(mSharedLibraries.get(name));
7134 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007135 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007136
7137 if ((dumpStar || dumpFeatures) && packageName == null) {
7138 if (printedTitle) pw.println(" ");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007139 printedTitle = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007140 pw.println("Features:");
7141 Iterator<String> it = mAvailableFeatures.keySet().iterator();
7142 while (it.hasNext()) {
7143 String name = it.next();
7144 pw.print(" ");
7145 pw.println(name);
7146 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007147 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007148
7149 if (dumpStar || dumpResolvers) {
7150 if (mActivities.dump(pw, printedTitle
7151 ? "\nActivity Resolver Table:" : "Activity Resolver Table:",
7152 " ", packageName, showFilters)) {
7153 printedTitle = true;
7154 }
7155 if (mReceivers.dump(pw, printedTitle
7156 ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:",
7157 " ", packageName, showFilters)) {
7158 printedTitle = true;
7159 }
7160 if (mServices.dump(pw, printedTitle
7161 ? "\nService Resolver Table:" : "Service Resolver Table:",
7162 " ", packageName, showFilters)) {
7163 printedTitle = true;
7164 }
7165 if (mSettings.mPreferredActivities.dump(pw, printedTitle
7166 ? "\nPreferred Activities:" : "Preferred Activities:",
7167 " ", packageName, showFilters)) {
7168 printedTitle = true;
7169 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007170 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007171
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007172 boolean printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007173 if (dumpStar || dumpPermissions) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007175 if (packageName != null && !packageName.equals(p.sourcePackage)) {
7176 continue;
7177 }
7178 if (!printedSomething) {
7179 if (printedTitle) pw.println(" ");
7180 pw.println("Permissions:");
7181 printedSomething = true;
7182 printedTitle = true;
7183 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007184 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
7185 pw.print(Integer.toHexString(System.identityHashCode(p)));
7186 pw.println("):");
7187 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
7188 pw.print(" uid="); pw.print(p.uid);
7189 pw.print(" gids="); pw.print(arrayToString(p.gids));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007190 pw.print(" type="); pw.print(p.type);
7191 pw.print(" prot="); pw.println(p.protectionLevel);
7192 if (p.packageSetting != null) {
7193 pw.print(" packageSetting="); pw.println(p.packageSetting);
7194 }
7195 if (p.perm != null) {
7196 pw.print(" perm="); pw.println(p.perm);
7197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 }
7199 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007200
7201 if (dumpStar || dumpProviders) {
7202 printedSomething = false;
7203 for (PackageParser.Provider p : mProviders.values()) {
7204 if (packageName != null && !packageName.equals(p.info.packageName)) {
7205 continue;
7206 }
7207 if (!printedSomething) {
7208 if (printedTitle) pw.println(" ");
7209 pw.println("Registered ContentProviders:");
7210 printedSomething = true;
7211 printedTitle = true;
7212 }
7213 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
7214 pw.println(p.toString());
7215 }
7216 }
7217
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007218 printedSomething = false;
7219 SharedUserSetting packageSharedUser = null;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007220 if (dumpStar || dumpPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007221 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
7222 Date date = new Date();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007223 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007224 if (packageName != null && !packageName.equals(ps.realName)
7225 && !packageName.equals(ps.name)) {
7226 continue;
7227 }
7228 if (!printedSomething) {
7229 if (printedTitle) pw.println(" ");
7230 pw.println("Packages:");
7231 printedSomething = true;
7232 printedTitle = true;
7233 }
7234 packageSharedUser = ps.sharedUser;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007235 pw.print(" Package [");
7236 pw.print(ps.realName != null ? ps.realName : ps.name);
7237 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007238 pw.print(Integer.toHexString(System.identityHashCode(ps)));
7239 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007240 if (ps.realName != null) {
7241 pw.print(" compat name="); pw.println(ps.name);
7242 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007243 pw.print(" userId="); pw.print(ps.userId);
7244 pw.print(" gids="); pw.println(arrayToString(ps.gids));
7245 pw.print(" sharedUser="); pw.println(ps.sharedUser);
7246 pw.print(" pkg="); pw.println(ps.pkg);
7247 pw.print(" codePath="); pw.println(ps.codePathString);
7248 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
Kenny Root85387d72010-08-26 10:13:11 -07007249 pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
Kenny Root93565c4b2010-06-18 15:46:06 -07007250 pw.print(" obbPath="); pw.println(ps.obbPathString);
Kenny Root1174f712010-10-22 10:07:11 -07007251 pw.print(" versionCode="); pw.println(ps.versionCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 if (ps.pkg != null) {
Kenny Root1174f712010-10-22 10:07:11 -07007253 pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007254 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007255 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Kenny Root85387d72010-08-26 10:13:11 -07007256 if (ps.pkg.mOperationPending) {
7257 pw.println(" mOperationPending=true");
7258 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007259 pw.print(" supportsScreens=[");
7260 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007261 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007262 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
7263 if (!first) pw.print(", ");
7264 first = false;
7265 pw.print("small");
7266 }
7267 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007268 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007269 if (!first) pw.print(", ");
7270 first = false;
7271 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007272 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007273 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007274 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007275 if (!first) pw.print(", ");
7276 first = false;
7277 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007278 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007279 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007280 ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007281 if (!first) pw.print(", ");
7282 first = false;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007283 pw.print("xlarge");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007284 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007285 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007286 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007287 if (!first) pw.print(", ");
7288 first = false;
7289 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007290 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007291 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007292 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
7293 if (!first) pw.print(", ");
7294 first = false;
7295 pw.print("anyDensity");
7296 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007298 pw.println("]");
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007299 pw.print(" timeStamp=");
7300 date.setTime(ps.timeStamp); pw.println(sdf.format(date));
7301 pw.print(" firstInstallTime=");
7302 date.setTime(ps.firstInstallTime); pw.println(sdf.format(date));
7303 pw.print(" lastUpdateTime=");
7304 date.setTime(ps.lastUpdateTime); pw.println(sdf.format(date));
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007305 pw.print(" signatures="); pw.println(ps.signatures);
7306 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007307 pw.print(" haveGids="); pw.println(ps.haveGids);
7308 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007309 pw.print(" installStatus="); pw.print(ps.installStatus);
7310 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 if (ps.disabledComponents.size() > 0) {
7312 pw.println(" disabledComponents:");
7313 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007314 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 }
7316 }
7317 if (ps.enabledComponents.size() > 0) {
7318 pw.println(" enabledComponents:");
7319 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007320 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 }
7322 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007323 if (ps.grantedPermissions.size() > 0) {
7324 pw.println(" grantedPermissions:");
7325 for (String s : ps.grantedPermissions) {
7326 pw.print(" "); pw.println(s);
7327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 }
7330 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007331 printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007332 if (dumpStar || dumpPackages) {
7333 if (mSettings.mRenamedPackages.size() > 0) {
7334 for (HashMap.Entry<String, String> e
7335 : mSettings.mRenamedPackages.entrySet()) {
7336 if (packageName != null && !packageName.equals(e.getKey())
7337 && !packageName.equals(e.getValue())) {
7338 continue;
7339 }
7340 if (!printedSomething) {
7341 if (printedTitle) pw.println(" ");
7342 pw.println("Renamed packages:");
7343 printedSomething = true;
7344 printedTitle = true;
7345 }
7346 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
7347 pw.println(e.getValue());
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007348 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007349 }
7350 printedSomething = false;
7351 if (mSettings.mDisabledSysPackages.size() > 0) {
7352 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
7353 if (packageName != null && !packageName.equals(ps.realName)
7354 && !packageName.equals(ps.name)) {
7355 continue;
7356 }
7357 if (!printedSomething) {
7358 if (printedTitle) pw.println(" ");
7359 pw.println("Hidden system packages:");
7360 printedSomething = true;
7361 printedTitle = true;
7362 }
7363 pw.print(" Package [");
7364 pw.print(ps.realName != null ? ps.realName : ps.name);
7365 pw.print("] (");
7366 pw.print(Integer.toHexString(System.identityHashCode(ps)));
7367 pw.println("):");
7368 if (ps.realName != null) {
7369 pw.print(" compat name="); pw.println(ps.name);
7370 }
7371 pw.print(" userId="); pw.println(ps.userId);
7372 pw.print(" sharedUser="); pw.println(ps.sharedUser);
7373 pw.print(" codePath="); pw.println(ps.codePathString);
7374 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007375 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007376 }
7377 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007378 printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007379 if (dumpStar || dumpSharedUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007381 if (packageName != null && su != packageSharedUser) {
7382 continue;
7383 }
7384 if (!printedSomething) {
7385 if (printedTitle) pw.println(" ");
7386 pw.println("Shared users:");
7387 printedSomething = true;
7388 printedTitle = true;
7389 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007390 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
7391 pw.print(Integer.toHexString(System.identityHashCode(su)));
7392 pw.println("):");
7393 pw.print(" userId="); pw.print(su.userId);
7394 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 pw.println(" grantedPermissions:");
7396 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007397 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 }
7400 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007401
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007402 if ((dumpStar || dumpMessages) && packageName == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007403 if (printedTitle) pw.println(" ");
7404 printedTitle = true;
7405 pw.println("Settings parse messages:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007406 pw.print(mSettings.mReadMessages.toString());
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007407
7408 pw.println(" ");
7409 pw.println("Package warning messages:");
7410 File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007411 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007412 try {
7413 in = new FileInputStream(fname);
7414 int avail = in.available();
7415 byte[] data = new byte[avail];
7416 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007417 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007418 } catch (FileNotFoundException e) {
7419 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007420 } finally {
7421 if (in != null) {
7422 try {
7423 in.close();
7424 } catch (IOException e) {
7425 }
7426 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007427 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007429 }
7430 }
7431
7432 static final class BasePermission {
7433 final static int TYPE_NORMAL = 0;
7434 final static int TYPE_BUILTIN = 1;
7435 final static int TYPE_DYNAMIC = 2;
7436
7437 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007438 String sourcePackage;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007439 PackageSettingBase packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007440 final int type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007441 int protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 PackageParser.Permission perm;
7443 PermissionInfo pendingInfo;
7444 int uid;
7445 int[] gids;
7446
7447 BasePermission(String _name, String _sourcePackage, int _type) {
7448 name = _name;
7449 sourcePackage = _sourcePackage;
7450 type = _type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007451 // Default to most conservative protection level.
7452 protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
7453 }
7454
Jason parks1125d782011-01-12 09:47:26 -06007455 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007456 public String toString() {
7457 return "BasePermission{"
7458 + Integer.toHexString(System.identityHashCode(this))
7459 + " " + name + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 }
7461 }
7462
7463 static class PackageSignatures {
7464 private Signature[] mSignatures;
7465
7466 PackageSignatures(Signature[] sigs) {
7467 assignSignatures(sigs);
7468 }
7469
7470 PackageSignatures() {
7471 }
7472
7473 void writeXml(XmlSerializer serializer, String tagName,
7474 ArrayList<Signature> pastSignatures) throws IOException {
7475 if (mSignatures == null) {
7476 return;
7477 }
7478 serializer.startTag(null, tagName);
7479 serializer.attribute(null, "count",
7480 Integer.toString(mSignatures.length));
7481 for (int i=0; i<mSignatures.length; i++) {
7482 serializer.startTag(null, "cert");
7483 final Signature sig = mSignatures[i];
7484 final int sigHash = sig.hashCode();
7485 final int numPast = pastSignatures.size();
7486 int j;
7487 for (j=0; j<numPast; j++) {
7488 Signature pastSig = pastSignatures.get(j);
7489 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
7490 serializer.attribute(null, "index", Integer.toString(j));
7491 break;
7492 }
7493 }
7494 if (j >= numPast) {
7495 pastSignatures.add(sig);
7496 serializer.attribute(null, "index", Integer.toString(numPast));
7497 serializer.attribute(null, "key", sig.toCharsString());
7498 }
7499 serializer.endTag(null, "cert");
7500 }
7501 serializer.endTag(null, tagName);
7502 }
7503
7504 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
7505 throws IOException, XmlPullParserException {
7506 String countStr = parser.getAttributeValue(null, "count");
7507 if (countStr == null) {
7508 reportSettingsProblem(Log.WARN,
7509 "Error in package manager settings: <signatures> has"
7510 + " no count at " + parser.getPositionDescription());
7511 XmlUtils.skipCurrentTag(parser);
7512 }
7513 final int count = Integer.parseInt(countStr);
7514 mSignatures = new Signature[count];
7515 int pos = 0;
7516
7517 int outerDepth = parser.getDepth();
7518 int type;
7519 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7520 && (type != XmlPullParser.END_TAG
7521 || parser.getDepth() > outerDepth)) {
7522 if (type == XmlPullParser.END_TAG
7523 || type == XmlPullParser.TEXT) {
7524 continue;
7525 }
7526
7527 String tagName = parser.getName();
7528 if (tagName.equals("cert")) {
7529 if (pos < count) {
7530 String index = parser.getAttributeValue(null, "index");
7531 if (index != null) {
7532 try {
7533 int idx = Integer.parseInt(index);
7534 String key = parser.getAttributeValue(null, "key");
7535 if (key == null) {
7536 if (idx >= 0 && idx < pastSignatures.size()) {
7537 Signature sig = pastSignatures.get(idx);
7538 if (sig != null) {
7539 mSignatures[pos] = pastSignatures.get(idx);
7540 pos++;
7541 } else {
7542 reportSettingsProblem(Log.WARN,
7543 "Error in package manager settings: <cert> "
7544 + "index " + index + " is not defined at "
7545 + parser.getPositionDescription());
7546 }
7547 } else {
7548 reportSettingsProblem(Log.WARN,
7549 "Error in package manager settings: <cert> "
7550 + "index " + index + " is out of bounds at "
7551 + parser.getPositionDescription());
7552 }
7553 } else {
7554 while (pastSignatures.size() <= idx) {
7555 pastSignatures.add(null);
7556 }
7557 Signature sig = new Signature(key);
7558 pastSignatures.set(idx, sig);
7559 mSignatures[pos] = sig;
7560 pos++;
7561 }
7562 } catch (NumberFormatException e) {
7563 reportSettingsProblem(Log.WARN,
7564 "Error in package manager settings: <cert> "
7565 + "index " + index + " is not a number at "
7566 + parser.getPositionDescription());
7567 }
7568 } else {
7569 reportSettingsProblem(Log.WARN,
7570 "Error in package manager settings: <cert> has"
7571 + " no index at " + parser.getPositionDescription());
7572 }
7573 } else {
7574 reportSettingsProblem(Log.WARN,
7575 "Error in package manager settings: too "
7576 + "many <cert> tags, expected " + count
7577 + " at " + parser.getPositionDescription());
7578 }
7579 } else {
7580 reportSettingsProblem(Log.WARN,
7581 "Unknown element under <cert>: "
7582 + parser.getName());
7583 }
7584 XmlUtils.skipCurrentTag(parser);
7585 }
7586
7587 if (pos < count) {
7588 // Should never happen -- there is an error in the written
7589 // settings -- but if it does we don't want to generate
7590 // a bad array.
7591 Signature[] newSigs = new Signature[pos];
7592 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
7593 mSignatures = newSigs;
7594 }
7595 }
7596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597 private void assignSignatures(Signature[] sigs) {
7598 if (sigs == null) {
7599 mSignatures = null;
7600 return;
7601 }
7602 mSignatures = new Signature[sigs.length];
7603 for (int i=0; i<sigs.length; i++) {
7604 mSignatures[i] = sigs[i];
7605 }
7606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 @Override
7609 public String toString() {
7610 StringBuffer buf = new StringBuffer(128);
7611 buf.append("PackageSignatures{");
7612 buf.append(Integer.toHexString(System.identityHashCode(this)));
7613 buf.append(" [");
7614 if (mSignatures != null) {
7615 for (int i=0; i<mSignatures.length; i++) {
7616 if (i > 0) buf.append(", ");
7617 buf.append(Integer.toHexString(
7618 System.identityHashCode(mSignatures[i])));
7619 }
7620 }
7621 buf.append("]}");
7622 return buf.toString();
7623 }
7624 }
7625
7626 static class PreferredActivity extends IntentFilter {
7627 final int mMatch;
7628 final String[] mSetPackages;
7629 final String[] mSetClasses;
7630 final String[] mSetComponents;
7631 final ComponentName mActivity;
7632 final String mShortActivity;
7633 String mParseError;
7634
7635 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
7636 ComponentName activity) {
7637 super(filter);
7638 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
7639 mActivity = activity;
7640 mShortActivity = activity.flattenToShortString();
7641 mParseError = null;
7642 if (set != null) {
7643 final int N = set.length;
7644 String[] myPackages = new String[N];
7645 String[] myClasses = new String[N];
7646 String[] myComponents = new String[N];
7647 for (int i=0; i<N; i++) {
7648 ComponentName cn = set[i];
7649 if (cn == null) {
7650 mSetPackages = null;
7651 mSetClasses = null;
7652 mSetComponents = null;
7653 return;
7654 }
7655 myPackages[i] = cn.getPackageName().intern();
7656 myClasses[i] = cn.getClassName().intern();
7657 myComponents[i] = cn.flattenToShortString().intern();
7658 }
7659 mSetPackages = myPackages;
7660 mSetClasses = myClasses;
7661 mSetComponents = myComponents;
7662 } else {
7663 mSetPackages = null;
7664 mSetClasses = null;
7665 mSetComponents = null;
7666 }
7667 }
7668
7669 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
7670 IOException {
7671 mShortActivity = parser.getAttributeValue(null, "name");
7672 mActivity = ComponentName.unflattenFromString(mShortActivity);
7673 if (mActivity == null) {
7674 mParseError = "Bad activity name " + mShortActivity;
7675 }
7676 String matchStr = parser.getAttributeValue(null, "match");
7677 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
7678 String setCountStr = parser.getAttributeValue(null, "set");
7679 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
7680
7681 String[] myPackages = setCount > 0 ? new String[setCount] : null;
7682 String[] myClasses = setCount > 0 ? new String[setCount] : null;
7683 String[] myComponents = setCount > 0 ? new String[setCount] : null;
7684
7685 int setPos = 0;
7686
7687 int outerDepth = parser.getDepth();
7688 int type;
7689 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7690 && (type != XmlPullParser.END_TAG
7691 || parser.getDepth() > outerDepth)) {
7692 if (type == XmlPullParser.END_TAG
7693 || type == XmlPullParser.TEXT) {
7694 continue;
7695 }
7696
7697 String tagName = parser.getName();
7698 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
7699 // + parser.getDepth() + " tag=" + tagName);
7700 if (tagName.equals("set")) {
7701 String name = parser.getAttributeValue(null, "name");
7702 if (name == null) {
7703 if (mParseError == null) {
7704 mParseError = "No name in set tag in preferred activity "
7705 + mShortActivity;
7706 }
7707 } else if (setPos >= setCount) {
7708 if (mParseError == null) {
7709 mParseError = "Too many set tags in preferred activity "
7710 + mShortActivity;
7711 }
7712 } else {
7713 ComponentName cn = ComponentName.unflattenFromString(name);
7714 if (cn == null) {
7715 if (mParseError == null) {
7716 mParseError = "Bad set name " + name + " in preferred activity "
7717 + mShortActivity;
7718 }
7719 } else {
7720 myPackages[setPos] = cn.getPackageName();
7721 myClasses[setPos] = cn.getClassName();
7722 myComponents[setPos] = name;
7723 setPos++;
7724 }
7725 }
7726 XmlUtils.skipCurrentTag(parser);
7727 } else if (tagName.equals("filter")) {
7728 //Log.i(TAG, "Starting to parse filter...");
7729 readFromXml(parser);
7730 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
7731 // + parser.getDepth() + " tag=" + parser.getName());
7732 } else {
7733 reportSettingsProblem(Log.WARN,
7734 "Unknown element under <preferred-activities>: "
7735 + parser.getName());
7736 XmlUtils.skipCurrentTag(parser);
7737 }
7738 }
7739
7740 if (setPos != setCount) {
7741 if (mParseError == null) {
7742 mParseError = "Not enough set tags (expected " + setCount
7743 + " but found " + setPos + ") in " + mShortActivity;
7744 }
7745 }
7746
7747 mSetPackages = myPackages;
7748 mSetClasses = myClasses;
7749 mSetComponents = myComponents;
7750 }
7751
Jason parks1125d782011-01-12 09:47:26 -06007752 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 public void writeToXml(XmlSerializer serializer) throws IOException {
7754 final int NS = mSetClasses != null ? mSetClasses.length : 0;
7755 serializer.attribute(null, "name", mShortActivity);
7756 serializer.attribute(null, "match", Integer.toHexString(mMatch));
7757 serializer.attribute(null, "set", Integer.toString(NS));
7758 for (int s=0; s<NS; s++) {
7759 serializer.startTag(null, "set");
7760 serializer.attribute(null, "name", mSetComponents[s]);
7761 serializer.endTag(null, "set");
7762 }
7763 serializer.startTag(null, "filter");
7764 super.writeToXml(serializer);
7765 serializer.endTag(null, "filter");
7766 }
7767
7768 boolean sameSet(List<ResolveInfo> query, int priority) {
7769 if (mSetPackages == null) return false;
7770 final int NQ = query.size();
7771 final int NS = mSetPackages.length;
7772 int numMatch = 0;
7773 for (int i=0; i<NQ; i++) {
7774 ResolveInfo ri = query.get(i);
7775 if (ri.priority != priority) continue;
7776 ActivityInfo ai = ri.activityInfo;
7777 boolean good = false;
7778 for (int j=0; j<NS; j++) {
7779 if (mSetPackages[j].equals(ai.packageName)
7780 && mSetClasses[j].equals(ai.name)) {
7781 numMatch++;
7782 good = true;
7783 break;
7784 }
7785 }
7786 if (!good) return false;
7787 }
7788 return numMatch == NS;
7789 }
7790 }
7791
7792 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007793 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007795 HashSet<String> grantedPermissions = new HashSet<String>();
7796 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007799 setFlags(pkgFlags);
7800 }
7801
7802 void setFlags(int pkgFlags) {
Jeff Brown07330792010-03-30 19:57:08 -07007803 this.pkgFlags = pkgFlags & (
7804 ApplicationInfo.FLAG_SYSTEM |
7805 ApplicationInfo.FLAG_FORWARD_LOCK |
Jason parks1125d782011-01-12 09:47:26 -06007806 ApplicationInfo.FLAG_EXTERNAL_STORAGE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 }
7808 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 /**
7811 * Settings base class for pending and resolved classes.
7812 */
7813 static class PackageSettingBase extends GrantedPermissions {
7814 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007815 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007816 File codePath;
7817 String codePathString;
7818 File resourcePath;
7819 String resourcePathString;
Kenny Root85387d72010-08-26 10:13:11 -07007820 String nativeLibraryPathString;
Kenny Root93565c4b2010-06-18 15:46:06 -07007821 String obbPathString;
Kenny Root7d794fb2010-09-13 16:29:49 -07007822 long timeStamp;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007823 long firstInstallTime;
7824 long lastUpdateTime;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007825 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007827 boolean uidError;
7828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007829 PackageSignatures signatures = new PackageSignatures();
7830
7831 boolean permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007832 boolean haveGids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 /* Explicitly disabled components */
7835 HashSet<String> disabledComponents = new HashSet<String>(0);
7836 /* Explicitly enabled components */
7837 HashSet<String> enabledComponents = new HashSet<String>(0);
7838 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7839 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007840
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007841 PackageSettingBase origPackage;
7842
Jacek Surazski65e13172009-04-28 15:26:38 +02007843 /* package name of the app that installed this package */
7844 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007845
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007846 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07007847 String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 super(pkgFlags);
7849 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007850 this.realName = realName;
Kenny Root806cc132010-09-12 08:34:19 -07007851 init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007852 }
7853
Kenny Root806cc132010-09-12 08:34:19 -07007854 void init(File codePath, File resourcePath, String nativeLibraryPathString,
7855 int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007856 this.codePath = codePath;
7857 this.codePathString = codePath.toString();
7858 this.resourcePath = resourcePath;
7859 this.resourcePathString = resourcePath.toString();
Kenny Root806cc132010-09-12 08:34:19 -07007860 this.nativeLibraryPathString = nativeLibraryPathString;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007861 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 }
Kenny Root85387d72010-08-26 10:13:11 -07007863
Jacek Surazski65e13172009-04-28 15:26:38 +02007864 public void setInstallerPackageName(String packageName) {
7865 installerPackageName = packageName;
7866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007867
Jacek Surazski65e13172009-04-28 15:26:38 +02007868 String getInstallerPackageName() {
7869 return installerPackageName;
7870 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 public void setInstallStatus(int newStatus) {
7873 installStatus = newStatus;
7874 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 public int getInstallStatus() {
7877 return installStatus;
7878 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007880 public void setTimeStamp(long newStamp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 timeStamp = newStamp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 }
7883
7884 public void copyFrom(PackageSettingBase base) {
7885 grantedPermissions = base.grantedPermissions;
7886 gids = base.gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007888 timeStamp = base.timeStamp;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007889 firstInstallTime = base.firstInstallTime;
7890 lastUpdateTime = base.lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 signatures = base.signatures;
7892 permissionsFixed = base.permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007893 haveGids = base.haveGids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007894 disabledComponents = base.disabledComponents;
7895 enabledComponents = base.enabledComponents;
7896 enabled = base.enabled;
7897 installStatus = base.installStatus;
7898 }
7899
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007900 boolean enableComponentLP(String componentClassName) {
7901 boolean changed = disabledComponents.remove(componentClassName);
7902 changed |= enabledComponents.add(componentClassName);
7903 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 }
7905
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007906 boolean disableComponentLP(String componentClassName) {
7907 boolean changed = enabledComponents.remove(componentClassName);
7908 changed |= disabledComponents.add(componentClassName);
7909 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 }
7911
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007912 boolean restoreComponentLP(String componentClassName) {
7913 boolean changed = enabledComponents.remove(componentClassName);
7914 changed |= disabledComponents.remove(componentClassName);
7915 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007916 }
7917
7918 int currentEnabledStateLP(String componentName) {
7919 if (enabledComponents.contains(componentName)) {
7920 return COMPONENT_ENABLED_STATE_ENABLED;
7921 } else if (disabledComponents.contains(componentName)) {
7922 return COMPONENT_ENABLED_STATE_DISABLED;
7923 } else {
7924 return COMPONENT_ENABLED_STATE_DEFAULT;
7925 }
7926 }
7927 }
7928
7929 /**
7930 * Settings data for a particular package we know about.
7931 */
7932 static final class PackageSetting extends PackageSettingBase {
7933 int userId;
7934 PackageParser.Package pkg;
7935 SharedUserSetting sharedUser;
7936
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007937 PackageSetting(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07007938 String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
7939 super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
7940 pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007942
Dianne Hackborn690d20b2010-12-22 14:03:29 -08007943 PackageSetting(PackageSetting orig) {
7944 super(orig.name, orig.realName, orig.codePath, orig.resourcePath,
7945 orig.nativeLibraryPathString, orig.versionCode, orig.pkgFlags);
7946 copyFrom(orig);
7947 }
7948
Kenny Root97ef63b2011-01-11 11:15:35 -08007949 public void copyFrom(PackageSetting base) {
Jason parks1125d782011-01-12 09:47:26 -06007950 super.copyFrom(base);
Kenny Root97ef63b2011-01-11 11:15:35 -08007951
7952 userId = base.userId;
7953 sharedUser = base.sharedUser;
7954 pkg = base.pkg;
7955 }
7956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 @Override
7958 public String toString() {
7959 return "PackageSetting{"
7960 + Integer.toHexString(System.identityHashCode(this))
7961 + " " + name + "/" + userId + "}";
7962 }
7963 }
7964
7965 /**
7966 * Settings data for a particular shared user ID we know about.
7967 */
7968 static final class SharedUserSetting extends GrantedPermissions {
7969 final String name;
7970 int userId;
7971 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
7972 final PackageSignatures signatures = new PackageSignatures();
7973
7974 SharedUserSetting(String _name, int _pkgFlags) {
7975 super(_pkgFlags);
7976 name = _name;
7977 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007979 @Override
7980 public String toString() {
7981 return "SharedUserSetting{"
7982 + Integer.toHexString(System.identityHashCode(this))
7983 + " " + name + "/" + userId + "}";
7984 }
7985 }
7986
7987 /**
7988 * Holds information about dynamic settings.
7989 */
7990 private static final class Settings {
7991 private final File mSettingsFilename;
7992 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007993 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 private final HashMap<String, PackageSetting> mPackages =
7995 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007996 // List of replaced system applications
7997 final HashMap<String, PackageSetting> mDisabledSysPackages =
7998 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007999
Dianne Hackbornf22221f2010-04-05 18:35:42 -07008000 // These are the last platform API version we were using for
8001 // the apps installed on internal and external storage. It is
8002 // used to grant newer permissions one time during a system upgrade.
8003 int mInternalSdkPlatform;
8004 int mExternalSdkPlatform;
8005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 // The user's preferred activities associated with particular intent
8007 // filters.
8008 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
8009 new IntentResolver<PreferredActivity, PreferredActivity>() {
8010 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008011 protected String packageForFilter(PreferredActivity filter) {
8012 return filter.mActivity.getPackageName();
8013 }
8014 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008015 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008017 out.print(prefix); out.print(
8018 Integer.toHexString(System.identityHashCode(filter)));
8019 out.print(' ');
8020 out.print(filter.mActivity.flattenToShortString());
8021 out.print(" match=0x");
8022 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008024 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008025 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008026 out.print(prefix); out.print(" ");
8027 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 }
8029 }
8030 }
8031 };
8032 private final HashMap<String, SharedUserSetting> mSharedUsers =
8033 new HashMap<String, SharedUserSetting>();
8034 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
8035 private final SparseArray<Object> mOtherUserIds =
8036 new SparseArray<Object>();
8037
8038 // For reading/writing settings file.
8039 private final ArrayList<Signature> mPastSignatures =
8040 new ArrayList<Signature>();
8041
8042 // Mapping from permission names to info about them.
8043 final HashMap<String, BasePermission> mPermissions =
8044 new HashMap<String, BasePermission>();
8045
8046 // Mapping from permission tree names to info about them.
8047 final HashMap<String, BasePermission> mPermissionTrees =
8048 new HashMap<String, BasePermission>();
8049
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008050 // Packages that have been uninstalled and still need their external
8051 // storage data deleted.
8052 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
8053
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008054 // Packages that have been renamed since they were first installed.
8055 // Keys are the new names of the packages, values are the original
8056 // names. The packages appear everwhere else under their original
8057 // names.
8058 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
8059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 private final StringBuilder mReadMessages = new StringBuilder();
8061
8062 private static final class PendingPackage extends PackageSettingBase {
8063 final int sharedId;
8064
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008065 PendingPackage(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008066 String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) {
8067 super(name, realName, codePath, resourcePath, nativeLibraryPathString,
8068 pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 this.sharedId = sharedId;
8070 }
8071 }
8072 private final ArrayList<PendingPackage> mPendingPackages
8073 = new ArrayList<PendingPackage>();
8074
8075 Settings() {
8076 File dataDir = Environment.getDataDirectory();
8077 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08008078 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
8079 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008080 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008081 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 FileUtils.setPermissions(systemDir.toString(),
8083 FileUtils.S_IRWXU|FileUtils.S_IRWXG
8084 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
8085 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08008086 FileUtils.setPermissions(systemSecureDir.toString(),
8087 FileUtils.S_IRWXU|FileUtils.S_IRWXG
8088 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
8089 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008090 mSettingsFilename = new File(systemDir, "packages.xml");
8091 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008092 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008093 }
8094
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008095 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008096 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008097 String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008099 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Kenny Root806cc132010-09-12 08:34:19 -07008100 resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008101 return p;
8102 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008103
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008104 PackageSetting peekPackageLP(String name) {
8105 return mPackages.get(name);
8106 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008107 PackageSetting p = mPackages.get(name);
8108 if (p != null && p.codePath.getPath().equals(codePath)) {
8109 return p;
8110 }
8111 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008112 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 void setInstallStatus(String pkgName, int status) {
8116 PackageSetting p = mPackages.get(pkgName);
8117 if(p != null) {
8118 if(p.getInstallStatus() != status) {
8119 p.setInstallStatus(status);
8120 }
8121 }
8122 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008123
Jacek Surazski65e13172009-04-28 15:26:38 +02008124 void setInstallerPackageName(String pkgName,
8125 String installerPkgName) {
8126 PackageSetting p = mPackages.get(pkgName);
8127 if(p != null) {
8128 p.setInstallerPackageName(installerPkgName);
8129 }
8130 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008131
Jacek Surazski65e13172009-04-28 15:26:38 +02008132 String getInstallerPackageName(String pkgName) {
8133 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008134 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02008135 }
8136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 int getInstallStatus(String pkgName) {
8138 PackageSetting p = mPackages.get(pkgName);
8139 if(p != null) {
8140 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 return -1;
8143 }
8144
8145 SharedUserSetting getSharedUserLP(String name,
8146 int pkgFlags, boolean create) {
8147 SharedUserSetting s = mSharedUsers.get(name);
8148 if (s == null) {
8149 if (!create) {
8150 return null;
8151 }
8152 s = new SharedUserSetting(name, pkgFlags);
8153 if (MULTIPLE_APPLICATION_UIDS) {
8154 s.userId = newUserIdLP(s);
8155 } else {
8156 s.userId = FIRST_APPLICATION_UID;
8157 }
8158 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
8159 // < 0 means we couldn't assign a userid; fall out and return
8160 // s, which is currently null
8161 if (s.userId >= 0) {
8162 mSharedUsers.put(name, s);
8163 }
8164 }
8165
8166 return s;
8167 }
8168
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008169 boolean disableSystemPackageLP(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008170 PackageSetting p = mPackages.get(name);
8171 if(p == null) {
8172 Log.w(TAG, "Package:"+name+" is not an installed package");
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008173 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 }
8175 PackageSetting dp = mDisabledSysPackages.get(name);
8176 // always make sure the system package code and resource paths dont change
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008177 if (dp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
8179 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
8180 }
8181 mDisabledSysPackages.put(name, p);
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008182
8183 // a little trick... when we install the new package, we don't
8184 // want to modify the existing PackageSetting for the built-in
8185 // version. so at this point we need a new PackageSetting that
8186 // is okay to much with.
8187 PackageSetting newp = new PackageSetting(p);
8188 replacePackageLP(name, newp);
8189 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008191 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 PackageSetting enableSystemPackageLP(String name) {
8195 PackageSetting p = mDisabledSysPackages.get(name);
8196 if(p == null) {
8197 Log.w(TAG, "Package:"+name+" is not disabled");
8198 return null;
8199 }
8200 // Reset flag in ApplicationInfo object
8201 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
8202 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
8203 }
Kenny Root806cc132010-09-12 08:34:19 -07008204 PackageSetting ret = addPackageLP(name, p.realName, p.codePath, p.resourcePath,
8205 p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008206 mDisabledSysPackages.remove(name);
8207 return ret;
8208 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008209
Kenny Root806cc132010-09-12 08:34:19 -07008210 PackageSetting addPackageLP(String name, String realName, File codePath, File resourcePath,
8211 String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008212 PackageSetting p = mPackages.get(name);
8213 if (p != null) {
8214 if (p.userId == uid) {
8215 return p;
8216 }
8217 reportSettingsProblem(Log.ERROR,
8218 "Adding duplicate package, keeping first: " + name);
8219 return null;
8220 }
Kenny Root806cc132010-09-12 08:34:19 -07008221 p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
8222 vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 p.userId = uid;
8224 if (addUserIdLP(uid, p, name)) {
8225 mPackages.put(name, p);
8226 return p;
8227 }
8228 return null;
8229 }
8230
8231 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
8232 SharedUserSetting s = mSharedUsers.get(name);
8233 if (s != null) {
8234 if (s.userId == uid) {
8235 return s;
8236 }
8237 reportSettingsProblem(Log.ERROR,
8238 "Adding duplicate shared user, keeping first: " + name);
8239 return null;
8240 }
8241 s = new SharedUserSetting(name, pkgFlags);
8242 s.userId = uid;
8243 if (addUserIdLP(uid, s, name)) {
8244 mSharedUsers.put(name, s);
8245 return s;
8246 }
8247 return null;
8248 }
8249
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008250 // Transfer ownership of permissions from one package to another.
8251 private void transferPermissions(String origPkg, String newPkg) {
8252 // Transfer ownership of permissions to the new package.
8253 for (int i=0; i<2; i++) {
8254 HashMap<String, BasePermission> permissions =
8255 i == 0 ? mPermissionTrees : mPermissions;
8256 for (BasePermission bp : permissions.values()) {
8257 if (origPkg.equals(bp.sourcePackage)) {
8258 if (DEBUG_UPGRADE) Log.v(TAG,
8259 "Moving permission " + bp.name
8260 + " from pkg " + bp.sourcePackage
8261 + " to " + newPkg);
8262 bp.sourcePackage = newPkg;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008263 bp.packageSetting = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008264 bp.perm = null;
8265 if (bp.pendingInfo != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008266 bp.pendingInfo.packageName = newPkg;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008267 }
8268 bp.uid = 0;
8269 bp.gids = null;
8270 }
8271 }
8272 }
8273 }
8274
8275 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008276 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008277 String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 PackageSetting p = mPackages.get(name);
8279 if (p != null) {
8280 if (!p.codePath.equals(codePath)) {
8281 // Check to see if its a disabled system app
Kenny Rootbd135c12010-10-05 12:26:27 -07008282 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07008283 // This is an updated system app with versions in both system
8284 // and data partition. Just let the most recent version
8285 // take precedence.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008286 Slog.w(TAG, "Trying to update system app code path from " +
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008287 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07008288 } else {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08008289 // Just a change in the code path is not an issue, but
8290 // let's log a message about it.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008291 Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008292 + " to " + codePath + "; Retaining data and using new");
Kenny Rootbd135c12010-10-05 12:26:27 -07008293 /*
8294 * Since we've changed paths, we need to prefer the new
8295 * native library path over the one stored in the
8296 * package settings since we might have moved from
8297 * internal to external storage or vice versa.
8298 */
8299 p.nativeLibraryPathString = nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008300 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008301 }
8302 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008303 reportSettingsProblem(Log.WARN,
8304 "Package " + name + " shared user changed from "
8305 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
8306 + " to "
8307 + (sharedUser != null ? sharedUser.name : "<nothing>")
8308 + "; replacing with new");
8309 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008310 } else {
8311 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8312 // If what we are scanning is a system package, then
8313 // make it so, regardless of whether it was previously
8314 // installed only in the data partition.
8315 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008317 }
8318 }
8319 if (p == null) {
8320 // Create a new PackageSettings entry. this can end up here because
8321 // of code path mismatch or user id mismatch of an updated system partition
8322 if (!create) {
8323 return null;
8324 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008325 if (origPackage != null) {
8326 // We are consuming the data from an existing package.
Kenny Root806cc132010-09-12 08:34:19 -07008327 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
8328 nativeLibraryPathString, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008329 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
8330 + " is adopting original package " + origPackage.name);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008331 // Note that we will retain the new package's signature so
8332 // that we can keep its data.
8333 PackageSignatures s = p.signatures;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008334 p.copyFrom(origPackage);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008335 p.signatures = s;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008336 p.sharedUser = origPackage.sharedUser;
8337 p.userId = origPackage.userId;
8338 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008339 mRenamedPackages.put(name, origPackage.name);
8340 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008341 // Update new package state.
8342 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 } else {
Kenny Root806cc132010-09-12 08:34:19 -07008344 p = new PackageSetting(name, realName, codePath, resourcePath,
8345 nativeLibraryPathString, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008346 p.setTimeStamp(codePath.lastModified());
8347 p.sharedUser = sharedUser;
8348 if (sharedUser != null) {
8349 p.userId = sharedUser.userId;
8350 } else if (MULTIPLE_APPLICATION_UIDS) {
8351 // Clone the setting here for disabled system packages
8352 PackageSetting dis = mDisabledSysPackages.get(name);
8353 if (dis != null) {
8354 // For disabled packages a new setting is created
8355 // from the existing user id. This still has to be
8356 // added to list of user id's
8357 // Copy signatures from previous setting
8358 if (dis.signatures.mSignatures != null) {
8359 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
8360 }
8361 p.userId = dis.userId;
8362 // Clone permissions
8363 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008364 // Clone component info
8365 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
8366 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
8367 // Add new setting to list of user ids
8368 addUserIdLP(p.userId, p, name);
8369 } else {
8370 // Assign new user id
8371 p.userId = newUserIdLP(p);
8372 }
8373 } else {
8374 p.userId = FIRST_APPLICATION_UID;
8375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 }
8377 if (p.userId < 0) {
8378 reportSettingsProblem(Log.WARN,
8379 "Package " + name + " could not be assigned a valid uid");
8380 return null;
8381 }
8382 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008383 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008385 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008386 }
8387 }
8388 return p;
8389 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008390
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008391 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008392 p.pkg = pkg;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07008393 pkg.mSetEnabled = p.enabled;
Kenny Root85387d72010-08-26 10:13:11 -07008394 final String codePath = pkg.applicationInfo.sourceDir;
8395 final String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008396 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008397 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008398 Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008399 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008400 p.codePath = new File(codePath);
8401 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008402 }
8403 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008404 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008405 Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008406 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008407 p.resourcePath = new File(resourcePath);
8408 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008409 }
Kenny Root85387d72010-08-26 10:13:11 -07008410 // Update the native library path if needed
8411 final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
8412 if (nativeLibraryPath != null
8413 && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
8414 p.nativeLibraryPathString = nativeLibraryPath;
8415 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008416 // Update version code if needed
8417 if (pkg.mVersionCode != p.versionCode) {
8418 p.versionCode = pkg.mVersionCode;
8419 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008420 // Update signatures if needed.
8421 if (p.signatures.mSignatures == null) {
8422 p.signatures.assignSignatures(pkg.mSignatures);
8423 }
8424 // If this app defines a shared user id initialize
8425 // the shared user signatures as well.
8426 if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
8427 p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
8428 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008429 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
8430 }
8431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 // Utility method that adds a PackageSetting to mPackages and
8433 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008434 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008435 SharedUserSetting sharedUser) {
8436 mPackages.put(name, p);
8437 if (sharedUser != null) {
8438 if (p.sharedUser != null && p.sharedUser != sharedUser) {
8439 reportSettingsProblem(Log.ERROR,
8440 "Package " + p.name + " was user "
8441 + p.sharedUser + " but is now " + sharedUser
8442 + "; I am not changing its files so it will probably fail!");
8443 p.sharedUser.packages.remove(p);
8444 } else if (p.userId != sharedUser.userId) {
8445 reportSettingsProblem(Log.ERROR,
8446 "Package " + p.name + " was user id " + p.userId
8447 + " but is now user " + sharedUser
8448 + " with id " + sharedUser.userId
8449 + "; I am not changing its files so it will probably fail!");
8450 }
8451
8452 sharedUser.packages.add(p);
8453 p.sharedUser = sharedUser;
8454 p.userId = sharedUser.userId;
8455 }
8456 }
8457
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008458 /*
8459 * Update the shared user setting when a package using
8460 * specifying the shared user id is removed. The gids
8461 * associated with each permission of the deleted package
8462 * are removed from the shared user's gid list only if its
8463 * not in use by other permissions of packages in the
8464 * shared user setting.
8465 */
8466 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008468 Slog.i(TAG, "Trying to update info for null package. Just ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 return;
8470 }
8471 // No sharedUserId
8472 if (deletedPs.sharedUser == null) {
8473 return;
8474 }
8475 SharedUserSetting sus = deletedPs.sharedUser;
8476 // Update permissions
8477 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
8478 boolean used = false;
8479 if (!sus.grantedPermissions.contains (eachPerm)) {
8480 continue;
8481 }
8482 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008483 if (pkg.pkg != null &&
Dianne Hackbornf657b632010-03-22 18:08:07 -07008484 !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008485 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 used = true;
8487 break;
8488 }
8489 }
8490 if (!used) {
8491 // can safely delete this permission from list
8492 sus.grantedPermissions.remove(eachPerm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 }
8494 }
8495 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008496 int newGids[] = globalGids;
8497 for (String eachPerm : sus.grantedPermissions) {
8498 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008499 if (bp != null) {
8500 newGids = appendInts(newGids, bp.gids);
8501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 }
8503 sus.gids = newGids;
8504 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008506 private int removePackageLP(String name) {
8507 PackageSetting p = mPackages.get(name);
8508 if (p != null) {
8509 mPackages.remove(name);
8510 if (p.sharedUser != null) {
8511 p.sharedUser.packages.remove(p);
8512 if (p.sharedUser.packages.size() == 0) {
8513 mSharedUsers.remove(p.sharedUser.name);
8514 removeUserIdLP(p.sharedUser.userId);
8515 return p.sharedUser.userId;
8516 }
8517 } else {
8518 removeUserIdLP(p.userId);
8519 return p.userId;
8520 }
8521 }
8522 return -1;
8523 }
8524
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008525 private void replacePackageLP(String name, PackageSetting newp) {
8526 PackageSetting p = mPackages.get(name);
8527 if (p != null) {
8528 if (p.sharedUser != null) {
8529 p.sharedUser.packages.remove(p);
8530 p.sharedUser.packages.add(newp);
8531 } else {
8532 replaceUserIdLP(p.userId, newp);
8533 }
8534 }
8535 mPackages.put(name, newp);
8536 }
8537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008538 private boolean addUserIdLP(int uid, Object obj, Object name) {
8539 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
8540 return false;
8541 }
8542
8543 if (uid >= FIRST_APPLICATION_UID) {
8544 int N = mUserIds.size();
8545 final int index = uid - FIRST_APPLICATION_UID;
8546 while (index >= N) {
8547 mUserIds.add(null);
8548 N++;
8549 }
8550 if (mUserIds.get(index) != null) {
8551 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008552 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553 + " name=" + name);
8554 return false;
8555 }
8556 mUserIds.set(index, obj);
8557 } else {
8558 if (mOtherUserIds.get(uid) != null) {
8559 reportSettingsProblem(Log.ERROR,
8560 "Adding duplicate shared id: " + uid
8561 + " name=" + name);
8562 return false;
8563 }
8564 mOtherUserIds.put(uid, obj);
8565 }
8566 return true;
8567 }
8568
8569 public Object getUserIdLP(int uid) {
8570 if (uid >= FIRST_APPLICATION_UID) {
8571 int N = mUserIds.size();
8572 final int index = uid - FIRST_APPLICATION_UID;
8573 return index < N ? mUserIds.get(index) : null;
8574 } else {
8575 return mOtherUserIds.get(uid);
8576 }
8577 }
8578
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008579 private Set<String> findPackagesWithFlag(int flag) {
8580 Set<String> ret = new HashSet<String>();
8581 for (PackageSetting ps : mPackages.values()) {
8582 // Has to match atleast all the flag bits set on flag
8583 if ((ps.pkgFlags & flag) == flag) {
8584 ret.add(ps.name);
8585 }
8586 }
8587 return ret;
8588 }
8589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008590 private void removeUserIdLP(int uid) {
8591 if (uid >= FIRST_APPLICATION_UID) {
8592 int N = mUserIds.size();
8593 final int index = uid - FIRST_APPLICATION_UID;
8594 if (index < N) mUserIds.set(index, null);
8595 } else {
8596 mOtherUserIds.remove(uid);
8597 }
8598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008599
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008600 private void replaceUserIdLP(int uid, Object obj) {
8601 if (uid >= FIRST_APPLICATION_UID) {
8602 int N = mUserIds.size();
8603 final int index = uid - FIRST_APPLICATION_UID;
8604 if (index < N) mUserIds.set(index, obj);
8605 } else {
8606 mOtherUserIds.put(uid, obj);
8607 }
8608 }
8609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008610 void writeLP() {
8611 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
8612
8613 // Keep the old settings around until we know the new ones have
8614 // been successfully written.
8615 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008616 // Presence of backup settings file indicates that we failed
8617 // to persist settings earlier. So preserve the older
8618 // backup for future reference since the current settings
8619 // might have been corrupted.
8620 if (!mBackupSettingsFilename.exists()) {
8621 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008622 Slog.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008623 return;
8624 }
8625 } else {
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07008626 mSettingsFilename.delete();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008627 Slog.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07008628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 }
8630
8631 mPastSignatures.clear();
8632
8633 try {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07008634 FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
8635 BufferedOutputStream str = new BufferedOutputStream(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636
8637 //XmlSerializer serializer = XmlUtils.serializerInstance();
8638 XmlSerializer serializer = new FastXmlSerializer();
8639 serializer.setOutput(str, "utf-8");
8640 serializer.startDocument(null, true);
8641 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
8642
8643 serializer.startTag(null, "packages");
8644
Dianne Hackbornf22221f2010-04-05 18:35:42 -07008645 serializer.startTag(null, "last-platform-version");
8646 serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
8647 serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
8648 serializer.endTag(null, "last-platform-version");
8649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 serializer.startTag(null, "permission-trees");
8651 for (BasePermission bp : mPermissionTrees.values()) {
8652 writePermission(serializer, bp);
8653 }
8654 serializer.endTag(null, "permission-trees");
8655
8656 serializer.startTag(null, "permissions");
8657 for (BasePermission bp : mPermissions.values()) {
8658 writePermission(serializer, bp);
8659 }
8660 serializer.endTag(null, "permissions");
8661
8662 for (PackageSetting pkg : mPackages.values()) {
8663 writePackage(serializer, pkg);
8664 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 for (PackageSetting pkg : mDisabledSysPackages.values()) {
8667 writeDisabledSysPackage(serializer, pkg);
8668 }
8669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 serializer.startTag(null, "preferred-activities");
8671 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
8672 serializer.startTag(null, "item");
8673 pa.writeToXml(serializer);
8674 serializer.endTag(null, "item");
8675 }
8676 serializer.endTag(null, "preferred-activities");
8677
8678 for (SharedUserSetting usr : mSharedUsers.values()) {
8679 serializer.startTag(null, "shared-user");
8680 serializer.attribute(null, "name", usr.name);
8681 serializer.attribute(null, "userId",
8682 Integer.toString(usr.userId));
8683 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
8684 serializer.startTag(null, "perms");
8685 for (String name : usr.grantedPermissions) {
8686 serializer.startTag(null, "item");
8687 serializer.attribute(null, "name", name);
8688 serializer.endTag(null, "item");
8689 }
8690 serializer.endTag(null, "perms");
8691 serializer.endTag(null, "shared-user");
8692 }
8693
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008694 if (mPackagesToBeCleaned.size() > 0) {
8695 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
8696 serializer.startTag(null, "cleaning-package");
8697 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
8698 serializer.endTag(null, "cleaning-package");
8699 }
8700 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008701
8702 if (mRenamedPackages.size() > 0) {
8703 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
8704 serializer.startTag(null, "renamed-package");
8705 serializer.attribute(null, "new", e.getKey());
8706 serializer.attribute(null, "old", e.getValue());
8707 serializer.endTag(null, "renamed-package");
8708 }
8709 }
8710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008711 serializer.endTag(null, "packages");
8712
8713 serializer.endDocument();
8714
8715 str.flush();
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07008716 FileUtils.sync(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 str.close();
8718
8719 // New settings successfully written, old ones are no longer
8720 // needed.
8721 mBackupSettingsFilename.delete();
8722 FileUtils.setPermissions(mSettingsFilename.toString(),
8723 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8724 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8725 |FileUtils.S_IROTH,
8726 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008727
8728 // Write package list file now, use a JournaledFile.
8729 //
8730 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
8731 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
8732
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07008733 fstr = new FileOutputStream(journal.chooseForWrite());
8734 str = new BufferedOutputStream(fstr);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008735 try {
8736 StringBuilder sb = new StringBuilder();
8737 for (PackageSetting pkg : mPackages.values()) {
8738 ApplicationInfo ai = pkg.pkg.applicationInfo;
Kenny Root85387d72010-08-26 10:13:11 -07008739 String dataPath = ai.dataDir;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008740 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
8741
8742 // Avoid any application that has a space in its path
8743 // or that is handled by the system.
8744 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
8745 continue;
8746
8747 // we store on each line the following information for now:
8748 //
8749 // pkgName - package name
8750 // userId - application-specific user id
8751 // debugFlag - 0 or 1 if the package is debuggable.
8752 // dataPath - path to package's data path
8753 //
8754 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
8755 //
8756 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
8757 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
8758 // system/core/run-as/run-as.c
8759 //
8760 sb.setLength(0);
8761 sb.append(ai.packageName);
8762 sb.append(" ");
Jason parks1125d782011-01-12 09:47:26 -06008763 sb.append(ai.uid);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008764 sb.append(isDebug ? " 1 " : " 0 ");
8765 sb.append(dataPath);
8766 sb.append("\n");
8767 str.write(sb.toString().getBytes());
8768 }
8769 str.flush();
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07008770 FileUtils.sync(fstr);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008771 str.close();
8772 journal.commit();
8773 }
8774 catch (Exception e) {
8775 journal.rollback();
8776 }
8777
8778 FileUtils.setPermissions(mPackageListFilename.toString(),
8779 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8780 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8781 |FileUtils.S_IROTH,
8782 -1, -1);
8783
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008784 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008785
8786 } catch(XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008787 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008788 } catch(java.io.IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008789 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008791 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008792 if (mSettingsFilename.exists()) {
8793 if (!mSettingsFilename.delete()) {
8794 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
8795 }
8796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008797 //Debug.stopMethodTracing();
8798 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008799
8800 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008801 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008802 serializer.startTag(null, "updated-package");
8803 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008804 if (pkg.realName != null) {
8805 serializer.attribute(null, "realName", pkg.realName);
8806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008807 serializer.attribute(null, "codePath", pkg.codePathString);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008808 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
8809 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
8810 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008811 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8813 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8814 }
Kenny Root85387d72010-08-26 10:13:11 -07008815 if (pkg.nativeLibraryPathString != null) {
8816 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
8817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008818 if (pkg.sharedUser == null) {
8819 serializer.attribute(null, "userId",
8820 Integer.toString(pkg.userId));
8821 } else {
8822 serializer.attribute(null, "sharedUserId",
8823 Integer.toString(pkg.userId));
8824 }
8825 serializer.startTag(null, "perms");
8826 if (pkg.sharedUser == null) {
8827 // If this is a shared user, the permissions will
8828 // be written there. We still need to write an
8829 // empty permissions list so permissionsFixed will
8830 // be set.
8831 for (final String name : pkg.grantedPermissions) {
8832 BasePermission bp = mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008833 if (bp != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 // We only need to write signature or system permissions but this wont
8835 // match the semantics of grantedPermissions. So write all permissions.
8836 serializer.startTag(null, "item");
8837 serializer.attribute(null, "name", name);
8838 serializer.endTag(null, "item");
8839 }
8840 }
8841 }
8842 serializer.endTag(null, "perms");
8843 serializer.endTag(null, "updated-package");
8844 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008845
8846 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008847 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008848 serializer.startTag(null, "package");
8849 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008850 if (pkg.realName != null) {
8851 serializer.attribute(null, "realName", pkg.realName);
8852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008853 serializer.attribute(null, "codePath", pkg.codePathString);
8854 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8855 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8856 }
Kenny Root85387d72010-08-26 10:13:11 -07008857 if (pkg.nativeLibraryPathString != null) {
8858 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
8859 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008860 serializer.attribute(null, "flags",
8861 Integer.toString(pkg.pkgFlags));
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008862 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
8863 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
8864 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008865 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008866 if (pkg.sharedUser == null) {
8867 serializer.attribute(null, "userId",
8868 Integer.toString(pkg.userId));
8869 } else {
8870 serializer.attribute(null, "sharedUserId",
8871 Integer.toString(pkg.userId));
8872 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008873 if (pkg.uidError) {
8874 serializer.attribute(null, "uidError", "true");
8875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008876 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
8877 serializer.attribute(null, "enabled",
8878 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
8879 ? "true" : "false");
8880 }
8881 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
8882 serializer.attribute(null, "installStatus", "false");
8883 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008884 if (pkg.installerPackageName != null) {
8885 serializer.attribute(null, "installer", pkg.installerPackageName);
8886 }
Kenny Root93565c4b2010-06-18 15:46:06 -07008887 if (pkg.obbPathString != null) {
8888 serializer.attribute(null, "obbPath", pkg.obbPathString);
8889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
8891 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8892 serializer.startTag(null, "perms");
8893 if (pkg.sharedUser == null) {
8894 // If this is a shared user, the permissions will
8895 // be written there. We still need to write an
8896 // empty permissions list so permissionsFixed will
8897 // be set.
8898 for (final String name : pkg.grantedPermissions) {
8899 serializer.startTag(null, "item");
8900 serializer.attribute(null, "name", name);
8901 serializer.endTag(null, "item");
8902 }
8903 }
8904 serializer.endTag(null, "perms");
8905 }
8906 if (pkg.disabledComponents.size() > 0) {
8907 serializer.startTag(null, "disabled-components");
8908 for (final String name : pkg.disabledComponents) {
8909 serializer.startTag(null, "item");
8910 serializer.attribute(null, "name", name);
8911 serializer.endTag(null, "item");
8912 }
8913 serializer.endTag(null, "disabled-components");
8914 }
8915 if (pkg.enabledComponents.size() > 0) {
8916 serializer.startTag(null, "enabled-components");
8917 for (final String name : pkg.enabledComponents) {
8918 serializer.startTag(null, "item");
8919 serializer.attribute(null, "name", name);
8920 serializer.endTag(null, "item");
8921 }
8922 serializer.endTag(null, "enabled-components");
8923 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008925 serializer.endTag(null, "package");
8926 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 void writePermission(XmlSerializer serializer, BasePermission bp)
8929 throws XmlPullParserException, java.io.IOException {
8930 if (bp.type != BasePermission.TYPE_BUILTIN
8931 && bp.sourcePackage != null) {
8932 serializer.startTag(null, "item");
8933 serializer.attribute(null, "name", bp.name);
8934 serializer.attribute(null, "package", bp.sourcePackage);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008935 if (bp.protectionLevel !=
8936 PermissionInfo.PROTECTION_NORMAL) {
8937 serializer.attribute(null, "protection",
8938 Integer.toString(bp.protectionLevel));
8939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 if (DEBUG_SETTINGS) Log.v(TAG,
8941 "Writing perm: name=" + bp.name + " type=" + bp.type);
8942 if (bp.type == BasePermission.TYPE_DYNAMIC) {
8943 PermissionInfo pi = bp.perm != null ? bp.perm.info
8944 : bp.pendingInfo;
8945 if (pi != null) {
8946 serializer.attribute(null, "type", "dynamic");
8947 if (pi.icon != 0) {
8948 serializer.attribute(null, "icon",
8949 Integer.toString(pi.icon));
8950 }
8951 if (pi.nonLocalizedLabel != null) {
8952 serializer.attribute(null, "label",
8953 pi.nonLocalizedLabel.toString());
8954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008955 }
8956 }
8957 serializer.endTag(null, "item");
8958 }
8959 }
8960
8961 String getReadMessagesLP() {
8962 return mReadMessages.toString();
8963 }
8964
Oscar Montemayora8529f62009-11-18 10:14:20 -08008965 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008966 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
8967 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008968 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 while(its.hasNext()) {
8970 String key = its.next();
8971 PackageSetting ps = mPackages.get(key);
8972 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08008973 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008974 }
8975 }
8976 return ret;
8977 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 boolean readLP() {
8980 FileInputStream str = null;
8981 if (mBackupSettingsFilename.exists()) {
8982 try {
8983 str = new FileInputStream(mBackupSettingsFilename);
8984 mReadMessages.append("Reading from backup settings file\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07008985 reportSettingsProblem(Log.INFO, "Need to read from backup settings file");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008986 if (mSettingsFilename.exists()) {
8987 // If both the backup and settings file exist, we
8988 // ignore the settings since it might have been
8989 // corrupted.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008990 Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename);
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008991 mSettingsFilename.delete();
8992 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 } catch (java.io.IOException e) {
8994 // We'll try for the normal settings file.
8995 }
8996 }
8997
8998 mPastSignatures.clear();
8999
9000 try {
9001 if (str == null) {
9002 if (!mSettingsFilename.exists()) {
9003 mReadMessages.append("No settings file found\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07009004 reportSettingsProblem(Log.INFO, "No settings file; creating initial state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 return false;
9006 }
9007 str = new FileInputStream(mSettingsFilename);
9008 }
9009 XmlPullParser parser = Xml.newPullParser();
9010 parser.setInput(str, null);
9011
9012 int type;
9013 while ((type=parser.next()) != XmlPullParser.START_TAG
9014 && type != XmlPullParser.END_DOCUMENT) {
9015 ;
9016 }
9017
9018 if (type != XmlPullParser.START_TAG) {
9019 mReadMessages.append("No start tag found in settings file\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07009020 reportSettingsProblem(Log.WARN, "No start tag found in package manager settings");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 return false;
9022 }
9023
9024 int outerDepth = parser.getDepth();
9025 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9026 && (type != XmlPullParser.END_TAG
9027 || parser.getDepth() > outerDepth)) {
9028 if (type == XmlPullParser.END_TAG
9029 || type == XmlPullParser.TEXT) {
9030 continue;
9031 }
9032
9033 String tagName = parser.getName();
9034 if (tagName.equals("package")) {
9035 readPackageLP(parser);
9036 } else if (tagName.equals("permissions")) {
9037 readPermissionsLP(mPermissions, parser);
9038 } else if (tagName.equals("permission-trees")) {
9039 readPermissionsLP(mPermissionTrees, parser);
9040 } else if (tagName.equals("shared-user")) {
9041 readSharedUserLP(parser);
9042 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08009043 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009044 } else if (tagName.equals("preferred-activities")) {
9045 readPreferredActivitiesLP(parser);
9046 } else if(tagName.equals("updated-package")) {
9047 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009048 } else if (tagName.equals("cleaning-package")) {
9049 String name = parser.getAttributeValue(null, "name");
9050 if (name != null) {
9051 mPackagesToBeCleaned.add(name);
9052 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009053 } else if (tagName.equals("renamed-package")) {
9054 String nname = parser.getAttributeValue(null, "new");
9055 String oname = parser.getAttributeValue(null, "old");
9056 if (nname != null && oname != null) {
9057 mRenamedPackages.put(nname, oname);
9058 }
Dianne Hackbornf22221f2010-04-05 18:35:42 -07009059 } else if (tagName.equals("last-platform-version")) {
9060 mInternalSdkPlatform = mExternalSdkPlatform = 0;
9061 try {
9062 String internal = parser.getAttributeValue(null, "internal");
9063 if (internal != null) {
9064 mInternalSdkPlatform = Integer.parseInt(internal);
9065 }
9066 String external = parser.getAttributeValue(null, "external");
9067 if (external != null) {
Bryan Mawhinney2131a3c2010-04-23 14:38:31 +01009068 mExternalSdkPlatform = Integer.parseInt(external);
Dianne Hackbornf22221f2010-04-05 18:35:42 -07009069 }
9070 } catch (NumberFormatException e) {
9071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009072 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009073 Slog.w(TAG, "Unknown element under <packages>: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009074 + parser.getName());
9075 XmlUtils.skipCurrentTag(parser);
9076 }
9077 }
9078
9079 str.close();
9080
9081 } catch(XmlPullParserException e) {
9082 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackbornefb58102010-10-14 16:47:34 -07009083 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009084 Slog.e(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009085
9086 } catch(java.io.IOException e) {
9087 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackbornefb58102010-10-14 16:47:34 -07009088 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009089 Slog.e(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009090
9091 }
9092
9093 int N = mPendingPackages.size();
9094 for (int i=0; i<N; i++) {
9095 final PendingPackage pp = mPendingPackages.get(i);
9096 Object idObj = getUserIdLP(pp.sharedId);
9097 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009098 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
Kenny Root806cc132010-09-12 08:34:19 -07009099 (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
9100 pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009101 if (p == null) {
Dianne Hackbornefb58102010-10-14 16:47:34 -07009102 reportSettingsProblem(Log.WARN, "Unable to create application package for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009103 + pp.name);
9104 continue;
9105 }
9106 p.copyFrom(pp);
9107 } else if (idObj != null) {
9108 String msg = "Bad package setting: package " + pp.name
9109 + " has shared uid " + pp.sharedId
9110 + " that is not a shared uid\n";
9111 mReadMessages.append(msg);
Dianne Hackbornefb58102010-10-14 16:47:34 -07009112 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 } else {
9114 String msg = "Bad package setting: package " + pp.name
9115 + " has shared uid " + pp.sharedId
9116 + " that is not defined\n";
9117 mReadMessages.append(msg);
Dianne Hackbornefb58102010-10-14 16:47:34 -07009118 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009119 }
9120 }
9121 mPendingPackages.clear();
9122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009123 mReadMessages.append("Read completed successfully: "
9124 + mPackages.size() + " packages, "
9125 + mSharedUsers.size() + " shared uids\n");
9126
9127 return true;
9128 }
9129
9130 private int readInt(XmlPullParser parser, String ns, String name,
9131 int defValue) {
9132 String v = parser.getAttributeValue(ns, name);
9133 try {
9134 if (v == null) {
9135 return defValue;
9136 }
9137 return Integer.parseInt(v);
9138 } catch (NumberFormatException e) {
9139 reportSettingsProblem(Log.WARN,
9140 "Error in package manager settings: attribute " +
9141 name + " has bad integer value " + v + " at "
9142 + parser.getPositionDescription());
9143 }
9144 return defValue;
9145 }
9146
9147 private void readPermissionsLP(HashMap<String, BasePermission> out,
9148 XmlPullParser parser)
9149 throws IOException, XmlPullParserException {
9150 int outerDepth = parser.getDepth();
9151 int type;
9152 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9153 && (type != XmlPullParser.END_TAG
9154 || parser.getDepth() > outerDepth)) {
9155 if (type == XmlPullParser.END_TAG
9156 || type == XmlPullParser.TEXT) {
9157 continue;
9158 }
9159
9160 String tagName = parser.getName();
9161 if (tagName.equals("item")) {
9162 String name = parser.getAttributeValue(null, "name");
9163 String sourcePackage = parser.getAttributeValue(null, "package");
9164 String ptype = parser.getAttributeValue(null, "type");
9165 if (name != null && sourcePackage != null) {
9166 boolean dynamic = "dynamic".equals(ptype);
9167 BasePermission bp = new BasePermission(name, sourcePackage,
9168 dynamic
9169 ? BasePermission.TYPE_DYNAMIC
9170 : BasePermission.TYPE_NORMAL);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009171 bp.protectionLevel = readInt(parser, null, "protection",
9172 PermissionInfo.PROTECTION_NORMAL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 if (dynamic) {
9174 PermissionInfo pi = new PermissionInfo();
9175 pi.packageName = sourcePackage.intern();
9176 pi.name = name.intern();
9177 pi.icon = readInt(parser, null, "icon", 0);
9178 pi.nonLocalizedLabel = parser.getAttributeValue(
9179 null, "label");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009180 pi.protectionLevel = bp.protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 bp.pendingInfo = pi;
9182 }
9183 out.put(bp.name, bp);
9184 } else {
9185 reportSettingsProblem(Log.WARN,
9186 "Error in package manager settings: permissions has"
9187 + " no name at " + parser.getPositionDescription());
9188 }
9189 } else {
9190 reportSettingsProblem(Log.WARN,
9191 "Unknown element reading permissions: "
9192 + parser.getName() + " at "
9193 + parser.getPositionDescription());
9194 }
9195 XmlUtils.skipCurrentTag(parser);
9196 }
9197 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009200 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009202 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 String codePathStr = parser.getAttributeValue(null, "codePath");
9204 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Kenny Root806cc132010-09-12 08:34:19 -07009205 String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009206 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 resourcePathStr = codePathStr;
9208 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009209 String version = parser.getAttributeValue(null, "version");
9210 int versionCode = 0;
9211 if (version != null) {
9212 try {
9213 versionCode = Integer.parseInt(version);
9214 } catch (NumberFormatException e) {
9215 }
9216 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 int pkgFlags = 0;
9219 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Kenny Root806cc132010-09-12 08:34:19 -07009220 PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
9221 new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009222 String timeStampStr = parser.getAttributeValue(null, "ft");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009223 if (timeStampStr != null) {
9224 try {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009225 long timeStamp = Long.parseLong(timeStampStr, 16);
Kenny Root7d794fb2010-09-13 16:29:49 -07009226 ps.setTimeStamp(timeStamp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009227 } catch (NumberFormatException e) {
9228 }
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009229 } else {
9230 timeStampStr = parser.getAttributeValue(null, "ts");
9231 if (timeStampStr != null) {
9232 try {
9233 long timeStamp = Long.parseLong(timeStampStr);
9234 ps.setTimeStamp(timeStamp);
9235 } catch (NumberFormatException e) {
9236 }
9237 }
9238 }
9239 timeStampStr = parser.getAttributeValue(null, "it");
9240 if (timeStampStr != null) {
9241 try {
9242 ps.firstInstallTime = Long.parseLong(timeStampStr, 16);
9243 } catch (NumberFormatException e) {
9244 }
9245 }
9246 timeStampStr = parser.getAttributeValue(null, "ut");
9247 if (timeStampStr != null) {
9248 try {
9249 ps.lastUpdateTime = Long.parseLong(timeStampStr, 16);
9250 } catch (NumberFormatException e) {
9251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009252 }
9253 String idStr = parser.getAttributeValue(null, "userId");
9254 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
9255 if(ps.userId <= 0) {
9256 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
9257 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
9258 }
9259 int outerDepth = parser.getDepth();
9260 int type;
9261 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9262 && (type != XmlPullParser.END_TAG
9263 || parser.getDepth() > outerDepth)) {
9264 if (type == XmlPullParser.END_TAG
9265 || type == XmlPullParser.TEXT) {
9266 continue;
9267 }
9268
9269 String tagName = parser.getName();
9270 if (tagName.equals("perms")) {
9271 readGrantedPermissionsLP(parser,
9272 ps.grantedPermissions);
9273 } else {
9274 reportSettingsProblem(Log.WARN,
9275 "Unknown element under <updated-package>: "
9276 + parser.getName());
9277 XmlUtils.skipCurrentTag(parser);
9278 }
9279 }
9280 mDisabledSysPackages.put(name, ps);
9281 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009283 private void readPackageLP(XmlPullParser parser)
9284 throws XmlPullParserException, IOException {
9285 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009286 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 String idStr = null;
9288 String sharedIdStr = null;
9289 String codePathStr = null;
9290 String resourcePathStr = null;
Kenny Root85387d72010-08-26 10:13:11 -07009291 String nativeLibraryPathStr = null;
Kenny Root93565c4b2010-06-18 15:46:06 -07009292 String obbPathStr = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02009294 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009295 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009296 int pkgFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009297 long timeStamp = 0;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009298 long firstInstallTime = 0;
9299 long lastUpdateTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009301 String version = null;
9302 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009303 try {
9304 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009305 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009307 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
9309 codePathStr = parser.getAttributeValue(null, "codePath");
9310 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Kenny Root85387d72010-08-26 10:13:11 -07009311 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
Kenny Root93565c4b2010-06-18 15:46:06 -07009312 obbPathStr = parser.getAttributeValue(null, "obbPath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009313 version = parser.getAttributeValue(null, "version");
9314 if (version != null) {
9315 try {
9316 versionCode = Integer.parseInt(version);
9317 } catch (NumberFormatException e) {
9318 }
9319 }
Jacek Surazski65e13172009-04-28 15:26:38 +02009320 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009321
9322 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009323 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009324 try {
9325 pkgFlags = Integer.parseInt(systemStr);
9326 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009327 }
9328 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009329 // For backward compatibility
9330 systemStr = parser.getAttributeValue(null, "system");
9331 if (systemStr != null) {
9332 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
9333 } else {
9334 // Old settings that don't specify system... just treat
9335 // them as system, good enough.
9336 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
9337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 }
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009339 String timeStampStr = parser.getAttributeValue(null, "ft");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 if (timeStampStr != null) {
9341 try {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009342 timeStamp = Long.parseLong(timeStampStr, 16);
9343 } catch (NumberFormatException e) {
9344 }
9345 } else {
9346 timeStampStr = parser.getAttributeValue(null, "ts");
9347 if (timeStampStr != null) {
9348 try {
9349 timeStamp = Long.parseLong(timeStampStr);
9350 } catch (NumberFormatException e) {
9351 }
9352 }
9353 }
9354 timeStampStr = parser.getAttributeValue(null, "it");
9355 if (timeStampStr != null) {
9356 try {
9357 firstInstallTime = Long.parseLong(timeStampStr, 16);
9358 } catch (NumberFormatException e) {
9359 }
9360 }
9361 timeStampStr = parser.getAttributeValue(null, "ut");
9362 if (timeStampStr != null) {
9363 try {
9364 lastUpdateTime = Long.parseLong(timeStampStr, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 } catch (NumberFormatException e) {
9366 }
9367 }
9368 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
9369 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
9370 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
9371 if (resourcePathStr == null) {
9372 resourcePathStr = codePathStr;
9373 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009374 if (realName != null) {
9375 realName = realName.intern();
9376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009377 if (name == null) {
9378 reportSettingsProblem(Log.WARN,
9379 "Error in package manager settings: <package> has no name at "
9380 + parser.getPositionDescription());
9381 } else if (codePathStr == null) {
9382 reportSettingsProblem(Log.WARN,
9383 "Error in package manager settings: <package> has no codePath at "
9384 + parser.getPositionDescription());
9385 } else if (userId > 0) {
Kenny Root806cc132010-09-12 08:34:19 -07009386 packageSetting = addPackageLP(name.intern(), realName, new File(codePathStr),
9387 new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode,
9388 pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
9390 + ": userId=" + userId + " pkg=" + packageSetting);
9391 if (packageSetting == null) {
9392 reportSettingsProblem(Log.ERROR,
9393 "Failure adding uid " + userId
9394 + " while parsing settings at "
9395 + parser.getPositionDescription());
9396 } else {
Kenny Root7d794fb2010-09-13 16:29:49 -07009397 packageSetting.setTimeStamp(timeStamp);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009398 packageSetting.firstInstallTime = firstInstallTime;
9399 packageSetting.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009400 }
9401 } else if (sharedIdStr != null) {
9402 userId = sharedIdStr != null
9403 ? Integer.parseInt(sharedIdStr) : 0;
9404 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009405 packageSetting = new PendingPackage(name.intern(), realName,
9406 new File(codePathStr), new File(resourcePathStr),
Kenny Root806cc132010-09-12 08:34:19 -07009407 nativeLibraryPathStr, userId, versionCode, pkgFlags);
Kenny Root7d794fb2010-09-13 16:29:49 -07009408 packageSetting.setTimeStamp(timeStamp);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009409 packageSetting.firstInstallTime = firstInstallTime;
9410 packageSetting.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009411 mPendingPackages.add((PendingPackage) packageSetting);
9412 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
9413 + ": sharedUserId=" + userId + " pkg="
9414 + packageSetting);
9415 } else {
9416 reportSettingsProblem(Log.WARN,
9417 "Error in package manager settings: package "
9418 + name + " has bad sharedId " + sharedIdStr
9419 + " at " + parser.getPositionDescription());
9420 }
9421 } else {
9422 reportSettingsProblem(Log.WARN,
9423 "Error in package manager settings: package "
9424 + name + " has bad userId " + idStr + " at "
9425 + parser.getPositionDescription());
9426 }
9427 } catch (NumberFormatException e) {
9428 reportSettingsProblem(Log.WARN,
9429 "Error in package manager settings: package "
9430 + name + " has bad userId " + idStr + " at "
9431 + parser.getPositionDescription());
9432 }
9433 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009434 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02009435 packageSetting.installerPackageName = installerPackageName;
Kenny Root85387d72010-08-26 10:13:11 -07009436 packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
Kenny Root93565c4b2010-06-18 15:46:06 -07009437 packageSetting.obbPathString = obbPathStr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 final String enabledStr = parser.getAttributeValue(null, "enabled");
9439 if (enabledStr != null) {
9440 if (enabledStr.equalsIgnoreCase("true")) {
9441 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
9442 } else if (enabledStr.equalsIgnoreCase("false")) {
9443 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
9444 } else if (enabledStr.equalsIgnoreCase("default")) {
9445 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9446 } else {
9447 reportSettingsProblem(Log.WARN,
9448 "Error in package manager settings: package "
9449 + name + " has bad enabled value: " + idStr
9450 + " at " + parser.getPositionDescription());
9451 }
9452 } else {
9453 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9454 }
9455 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
9456 if (installStatusStr != null) {
9457 if (installStatusStr.equalsIgnoreCase("false")) {
9458 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
9459 } else {
9460 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
9461 }
9462 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 int outerDepth = parser.getDepth();
9465 int type;
9466 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9467 && (type != XmlPullParser.END_TAG
9468 || parser.getDepth() > outerDepth)) {
9469 if (type == XmlPullParser.END_TAG
9470 || type == XmlPullParser.TEXT) {
9471 continue;
9472 }
9473
9474 String tagName = parser.getName();
9475 if (tagName.equals("disabled-components")) {
9476 readDisabledComponentsLP(packageSetting, parser);
9477 } else if (tagName.equals("enabled-components")) {
9478 readEnabledComponentsLP(packageSetting, parser);
9479 } else if (tagName.equals("sigs")) {
9480 packageSetting.signatures.readXml(parser, mPastSignatures);
9481 } else if (tagName.equals("perms")) {
9482 readGrantedPermissionsLP(parser,
Dianne Hackbornf657b632010-03-22 18:08:07 -07009483 packageSetting.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 packageSetting.permissionsFixed = true;
9485 } else {
9486 reportSettingsProblem(Log.WARN,
9487 "Unknown element under <package>: "
9488 + parser.getName());
9489 XmlUtils.skipCurrentTag(parser);
9490 }
9491 }
9492 } else {
9493 XmlUtils.skipCurrentTag(parser);
9494 }
9495 }
9496
9497 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
9498 XmlPullParser parser)
9499 throws IOException, XmlPullParserException {
9500 int outerDepth = parser.getDepth();
9501 int type;
9502 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9503 && (type != XmlPullParser.END_TAG
9504 || parser.getDepth() > outerDepth)) {
9505 if (type == XmlPullParser.END_TAG
9506 || type == XmlPullParser.TEXT) {
9507 continue;
9508 }
9509
9510 String tagName = parser.getName();
9511 if (tagName.equals("item")) {
9512 String name = parser.getAttributeValue(null, "name");
9513 if (name != null) {
9514 packageSetting.disabledComponents.add(name.intern());
9515 } else {
9516 reportSettingsProblem(Log.WARN,
9517 "Error in package manager settings: <disabled-components> has"
9518 + " no name at " + parser.getPositionDescription());
9519 }
9520 } else {
9521 reportSettingsProblem(Log.WARN,
9522 "Unknown element under <disabled-components>: "
9523 + parser.getName());
9524 }
9525 XmlUtils.skipCurrentTag(parser);
9526 }
9527 }
9528
9529 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
9530 XmlPullParser parser)
9531 throws IOException, XmlPullParserException {
9532 int outerDepth = parser.getDepth();
9533 int type;
9534 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9535 && (type != XmlPullParser.END_TAG
9536 || parser.getDepth() > outerDepth)) {
9537 if (type == XmlPullParser.END_TAG
9538 || type == XmlPullParser.TEXT) {
9539 continue;
9540 }
9541
9542 String tagName = parser.getName();
9543 if (tagName.equals("item")) {
9544 String name = parser.getAttributeValue(null, "name");
9545 if (name != null) {
9546 packageSetting.enabledComponents.add(name.intern());
9547 } else {
9548 reportSettingsProblem(Log.WARN,
9549 "Error in package manager settings: <enabled-components> has"
9550 + " no name at " + parser.getPositionDescription());
9551 }
9552 } else {
9553 reportSettingsProblem(Log.WARN,
9554 "Unknown element under <enabled-components>: "
9555 + parser.getName());
9556 }
9557 XmlUtils.skipCurrentTag(parser);
9558 }
9559 }
9560
9561 private void readSharedUserLP(XmlPullParser parser)
9562 throws XmlPullParserException, IOException {
9563 String name = null;
9564 String idStr = null;
9565 int pkgFlags = 0;
9566 SharedUserSetting su = null;
9567 try {
9568 name = parser.getAttributeValue(null, "name");
9569 idStr = parser.getAttributeValue(null, "userId");
9570 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
9571 if ("true".equals(parser.getAttributeValue(null, "system"))) {
9572 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
9573 }
9574 if (name == null) {
9575 reportSettingsProblem(Log.WARN,
9576 "Error in package manager settings: <shared-user> has no name at "
9577 + parser.getPositionDescription());
9578 } else if (userId == 0) {
9579 reportSettingsProblem(Log.WARN,
9580 "Error in package manager settings: shared-user "
9581 + name + " has bad userId " + idStr + " at "
9582 + parser.getPositionDescription());
9583 } else {
9584 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
9585 reportSettingsProblem(Log.ERROR,
9586 "Occurred while parsing settings at "
9587 + parser.getPositionDescription());
9588 }
9589 }
9590 } catch (NumberFormatException e) {
9591 reportSettingsProblem(Log.WARN,
9592 "Error in package manager settings: package "
9593 + name + " has bad userId " + idStr + " at "
9594 + parser.getPositionDescription());
9595 };
9596
9597 if (su != null) {
9598 int outerDepth = parser.getDepth();
9599 int type;
9600 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9601 && (type != XmlPullParser.END_TAG
9602 || parser.getDepth() > outerDepth)) {
9603 if (type == XmlPullParser.END_TAG
9604 || type == XmlPullParser.TEXT) {
9605 continue;
9606 }
9607
9608 String tagName = parser.getName();
9609 if (tagName.equals("sigs")) {
9610 su.signatures.readXml(parser, mPastSignatures);
9611 } else if (tagName.equals("perms")) {
Dianne Hackbornf657b632010-03-22 18:08:07 -07009612 readGrantedPermissionsLP(parser, su.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 } else {
9614 reportSettingsProblem(Log.WARN,
9615 "Unknown element under <shared-user>: "
9616 + parser.getName());
9617 XmlUtils.skipCurrentTag(parser);
9618 }
9619 }
9620
9621 } else {
9622 XmlUtils.skipCurrentTag(parser);
9623 }
9624 }
9625
9626 private void readGrantedPermissionsLP(XmlPullParser parser,
9627 HashSet<String> outPerms) throws IOException, XmlPullParserException {
9628 int outerDepth = parser.getDepth();
9629 int type;
9630 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9631 && (type != XmlPullParser.END_TAG
9632 || parser.getDepth() > outerDepth)) {
9633 if (type == XmlPullParser.END_TAG
9634 || type == XmlPullParser.TEXT) {
9635 continue;
9636 }
9637
9638 String tagName = parser.getName();
9639 if (tagName.equals("item")) {
9640 String name = parser.getAttributeValue(null, "name");
9641 if (name != null) {
9642 outPerms.add(name.intern());
9643 } else {
9644 reportSettingsProblem(Log.WARN,
9645 "Error in package manager settings: <perms> has"
9646 + " no name at " + parser.getPositionDescription());
9647 }
9648 } else {
9649 reportSettingsProblem(Log.WARN,
9650 "Unknown element under <perms>: "
9651 + parser.getName());
9652 }
9653 XmlUtils.skipCurrentTag(parser);
9654 }
9655 }
9656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009657 private void readPreferredActivitiesLP(XmlPullParser parser)
9658 throws XmlPullParserException, IOException {
9659 int outerDepth = parser.getDepth();
9660 int type;
9661 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9662 && (type != XmlPullParser.END_TAG
9663 || parser.getDepth() > outerDepth)) {
9664 if (type == XmlPullParser.END_TAG
9665 || type == XmlPullParser.TEXT) {
9666 continue;
9667 }
9668
9669 String tagName = parser.getName();
9670 if (tagName.equals("item")) {
9671 PreferredActivity pa = new PreferredActivity(parser);
9672 if (pa.mParseError == null) {
9673 mPreferredActivities.addFilter(pa);
9674 } else {
9675 reportSettingsProblem(Log.WARN,
9676 "Error in package manager settings: <preferred-activity> "
9677 + pa.mParseError + " at "
9678 + parser.getPositionDescription());
9679 }
9680 } else {
9681 reportSettingsProblem(Log.WARN,
9682 "Unknown element under <preferred-activities>: "
9683 + parser.getName());
9684 XmlUtils.skipCurrentTag(parser);
9685 }
9686 }
9687 }
9688
9689 // Returns -1 if we could not find an available UserId to assign
9690 private int newUserIdLP(Object obj) {
9691 // Let's be stupidly inefficient for now...
9692 final int N = mUserIds.size();
9693 for (int i=0; i<N; i++) {
9694 if (mUserIds.get(i) == null) {
9695 mUserIds.set(i, obj);
9696 return FIRST_APPLICATION_UID + i;
9697 }
9698 }
9699
9700 // None left?
9701 if (N >= MAX_APPLICATION_UIDS) {
9702 return -1;
9703 }
9704
9705 mUserIds.add(obj);
9706 return FIRST_APPLICATION_UID + N;
9707 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 public PackageSetting getDisabledSystemPkg(String name) {
9710 synchronized(mPackages) {
9711 PackageSetting ps = mDisabledSysPackages.get(name);
9712 return ps;
9713 }
9714 }
9715
9716 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
Dianne Hackborn46730fc2010-07-24 16:32:42 -07009717 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
9718 return true;
9719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009720 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
9721 if (Config.LOGV) {
9722 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
9723 + " componentName = " + componentInfo.name);
9724 Log.v(TAG, "enabledComponents: "
9725 + Arrays.toString(packageSettings.enabledComponents.toArray()));
9726 Log.v(TAG, "disabledComponents: "
9727 + Arrays.toString(packageSettings.disabledComponents.toArray()));
9728 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009729 if (packageSettings == null) {
9730 if (false) {
9731 Log.w(TAG, "WAITING FOR DEBUGGER");
9732 Debug.waitForDebugger();
9733 Log.i(TAG, "We will crash!");
9734 }
Dianne Hackborn46730fc2010-07-24 16:32:42 -07009735 return false;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009736 }
Dianne Hackborn46730fc2010-07-24 16:32:42 -07009737 if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
9738 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
9739 && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
9740 return false;
9741 }
9742 if (packageSettings.enabledComponents.contains(componentInfo.name)) {
9743 return true;
9744 }
9745 if (packageSettings.disabledComponents.contains(componentInfo.name)) {
9746 return false;
9747 }
9748 return componentInfo.enabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009749 }
9750 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009751
9752 // ------- apps on sdcard specific code -------
9753 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root305bcbf2010-09-03 07:56:38 -07009754 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
9755 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
9756 static final int MAX_CONTAINERS = 250;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009757 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009758
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009759 private String getEncryptKey() {
9760 try {
Kenny Root305bcbf2010-09-03 07:56:38 -07009761 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
9762 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009763 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -07009764 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
9765 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009766 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009767 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009768 return null;
9769 }
9770 }
9771 return sdEncKey;
9772 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009773 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009774 return null;
Rich Cannings8d578832010-09-09 15:12:40 -07009775 } catch (IOException ioe) {
9776 Slog.e(TAG, "Failed to retrieve encryption keys with exception: "
9777 + ioe);
9778 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009779 }
Rich Cannings8d578832010-09-09 15:12:40 -07009780
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009781 }
9782
Kenny Rootc78a8072010-07-27 15:18:38 -07009783 /* package */ static String getTempContainerId() {
9784 int tmpIdx = 1;
9785 String list[] = PackageHelper.getSecureContainerList();
9786 if (list != null) {
9787 for (final String name : list) {
9788 // Ignore null and non-temporary container entries
9789 if (name == null || !name.startsWith(mTempContainerPrefix)) {
9790 continue;
9791 }
9792
9793 String subStr = name.substring(mTempContainerPrefix.length());
9794 try {
9795 int cid = Integer.parseInt(subStr);
9796 if (cid >= tmpIdx) {
9797 tmpIdx = cid + 1;
9798 }
9799 } catch (NumberFormatException e) {
9800 }
9801 }
9802 }
9803 return mTempContainerPrefix + tmpIdx;
9804 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009805
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009806 /*
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009807 * Update media status on PackageManager.
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009808 */
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009809 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
Marco Nelissen584f1372010-05-24 16:34:30 -07009810 int callingUid = Binder.getCallingUid();
9811 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009812 throw new SecurityException("Media status can only be updated by the system");
9813 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009814 synchronized (mPackages) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08009815 Log.i(TAG, "Updating external media status from " +
9816 (mMediaMounted ? "mounted" : "unmounted") + " to " +
9817 (mediaStatus ? "mounted" : "unmounted"));
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009818 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
9819 mediaStatus+", mMediaMounted=" + mMediaMounted);
9820 if (mediaStatus == mMediaMounted) {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009821 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
9822 reportStatus ? 1 : 0, -1);
9823 mHandler.sendMessage(msg);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009824 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009825 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009826 mMediaMounted = mediaStatus;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009827 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009828 // Queue up an async operation since the package installation may take a little while.
9829 mHandler.post(new Runnable() {
9830 public void run() {
9831 mHandler.removeCallbacks(this);
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009832 updateExternalMediaStatusInner(mediaStatus, reportStatus);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009833 }
9834 });
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009835 }
9836
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009837 /*
9838 * Collect information of applications on external media, map them
9839 * against existing containers and update information based on current
9840 * mount status. Please note that we always have to report status
9841 * if reportStatus has been set to true especially when unloading packages.
9842 */
9843 private void updateExternalMediaStatusInner(boolean mediaStatus,
9844 boolean reportStatus) {
9845 // Collection of uids
9846 int uidArr[] = null;
9847 // Collection of stale containers
9848 HashSet<String> removeCids = new HashSet<String>();
9849 // Collection of packages on external media with valid containers.
9850 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
9851 // Get list of secure containers.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08009852 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009853 if (list == null || list.length == 0) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08009854 Log.i(TAG, "No secure containers on sdcard");
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009855 } else {
9856 // Process list of secure containers and categorize them
9857 // as active or stale based on their package internal state.
9858 int uidList[] = new int[list.length];
9859 int num = 0;
9860 synchronized (mPackages) {
9861 for (String cid : list) {
9862 SdInstallArgs args = new SdInstallArgs(cid);
9863 if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009864 String pkgName = args.getPackageName();
9865 if (pkgName == null) {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009866 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
9867 removeCids.add(cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009868 continue;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009869 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009870 if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
9871 PackageSetting ps = mSettings.mPackages.get(pkgName);
Suchi Amalapurapu1ace5bc2010-05-13 12:05:53 -07009872 // The package status is changed only if the code path
9873 // matches between settings and the container id.
9874 if (ps != null && ps.codePathString != null &&
9875 ps.codePathString.equals(args.getCodePath())) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009876 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
9877 " corresponds to pkg : " + pkgName +
9878 " at code path: " + ps.codePathString);
9879 // We do have a valid package installed on sdcard
9880 processCids.put(args, ps.codePathString);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009881 int uid = ps.userId;
9882 if (uid != -1) {
9883 uidList[num++] = uid;
9884 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009885 } else {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009886 // Stale container on sdcard. Just delete
9887 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
9888 removeCids.add(cid);
9889 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009890 }
9891 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009892
9893 if (num > 0) {
9894 // Sort uid list
9895 Arrays.sort(uidList, 0, num);
9896 // Throw away duplicates
9897 uidArr = new int[num];
9898 uidArr[0] = uidList[0];
9899 int di = 0;
9900 for (int i = 1; i < num; i++) {
9901 if (uidList[i-1] != uidList[i]) {
9902 uidArr[di++] = uidList[i];
9903 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009904 }
9905 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009906 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009907 // Process packages with valid entries.
9908 if (mediaStatus) {
9909 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009910 loadMediaPackages(processCids, uidArr, removeCids);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009911 startCleaningPackages();
9912 } else {
9913 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009914 unloadMediaPackages(processCids, uidArr, reportStatus);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009915 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009916 }
9917
9918 private void sendResourcesChangedBroadcast(boolean mediaStatus,
Dianne Hackbornecb0e632010-04-07 20:22:55 -07009919 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009920 int size = pkgList.size();
9921 if (size > 0) {
9922 // Send broadcasts here
9923 Bundle extras = new Bundle();
9924 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
9925 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009926 if (uidArr != null) {
9927 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
9928 }
9929 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
9930 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Dianne Hackbornecb0e632010-04-07 20:22:55 -07009931 sendPackageBroadcast(action, null, extras, finishedReceiver);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009932 }
9933 }
9934
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009935 /*
9936 * Look at potentially valid container ids from processCids
9937 * If package information doesn't match the one on record
9938 * or package scanning fails, the cid is added to list of
Suchi Amalapurapu3d244252010-04-08 14:37:05 -07009939 * removeCids. We currently don't delete stale containers.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009940 */
9941 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009942 int uidArr[], HashSet<String> removeCids) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009943 ArrayList<String> pkgList = new ArrayList<String>();
9944 Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009945 boolean doGc = false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009946 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009947 String codePath = processCids.get(args);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009948 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : "
9949 + args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009950 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009951 try {
9952 // Make sure there are no container errors first.
9953 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED)
9954 != PackageManager.INSTALL_SUCCEEDED) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009955 Slog.e(TAG, "Failed to mount cid : " + args.cid +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009956 " when installing from sdcard");
9957 continue;
9958 }
9959 // Check code path here.
9960 if (codePath == null || !codePath.equals(args.getCodePath())) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009961 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009962 " does not match one in settings " + codePath);
9963 continue;
9964 }
9965 // Parse package
Dianne Hackborn399cccb2010-04-13 22:57:49 -07009966 int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009967 doGc = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009968 synchronized (mInstallLock) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009969 final PackageParser.Package pkg = scanPackageLI(new File(codePath),
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009970 parseFlags, 0, 0);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009971 // Scan the package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009972 if (pkg != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009973 synchronized (mPackages) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009974 retCode = PackageManager.INSTALL_SUCCEEDED;
9975 pkgList.add(pkg.packageName);
9976 // Post process args
9977 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
9978 }
9979 } else {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009980 Slog.i(TAG, "Failed to install pkg from " +
9981 codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009982 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009983 }
9984
9985 } finally {
9986 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
9987 // Don't destroy container here. Wait till gc clears things up.
9988 removeCids.add(args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009989 }
9990 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009991 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009992 synchronized (mPackages) {
Dianne Hackbornf22221f2010-04-05 18:35:42 -07009993 // If the platform SDK has changed since the last time we booted,
9994 // we need to re-grant app permission to catch any new ones that
9995 // appear. This is really a hack, and means that apps can in some
9996 // cases get permissions that the user didn't initially explicitly
9997 // allow... it would be nice to have some better way to handle
9998 // this situation.
9999 final boolean regrantPermissions = mSettings.mExternalSdkPlatform
10000 != mSdkVersion;
10001 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
10002 + mSettings.mExternalSdkPlatform + " to " + mSdkVersion
10003 + "; regranting permissions for external storage");
10004 mSettings.mExternalSdkPlatform = mSdkVersion;
10005
Dianne Hackbornaf7cea32010-03-24 12:59:52 -070010006 // Make sure group IDs have been assigned, and any permission
10007 // changes in other apps are accounted for
Dianne Hackborn92cfa102010-04-28 11:00:44 -070010008 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010009 // Persist settings
10010 mSettings.writeLP();
10011 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080010012 // Send a broadcast to let everyone know we are done processing
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010013 if (pkgList.size() > 0) {
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010014 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010015 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010016 // Force gc to avoid any stale parser references that we might have.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010017 if (doGc) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010018 Runtime.getRuntime().gc();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010019 }
Kenny Rootf369a9b2010-07-28 14:47:01 -070010020 // List stale containers and destroy stale temporary containers.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010021 if (removeCids != null) {
10022 for (String cid : removeCids) {
Kenny Rootf369a9b2010-07-28 14:47:01 -070010023 if (cid.startsWith(mTempContainerPrefix)) {
10024 Log.i(TAG, "Destroying stale temporary container " + cid);
10025 PackageHelper.destroySdDir(cid);
10026 } else {
10027 Log.w(TAG, "Container " + cid + " is stale");
10028 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010029 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010030 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010031 }
10032
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010033 /*
10034 * Utility method to unload a list of specified containers
10035 */
10036 private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
10037 // Just unmount all valid containers.
10038 for (SdInstallArgs arg : cidArgs) {
10039 synchronized (mInstallLock) {
10040 arg.doPostDeleteLI(false);
10041 }
10042 }
10043 }
10044
10045 /*
10046 * Unload packages mounted on external media. This involves deleting
10047 * package data from internal structures, sending broadcasts about
10048 * diabled packages, gc'ing to free up references, unmounting all
10049 * secure containers corresponding to packages on external media, and
10050 * posting a UPDATED_MEDIA_STATUS message if status has been requested.
10051 * Please note that we always have to post this message if status has
10052 * been requested no matter what.
10053 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010054 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010055 int uidArr[], final boolean reportStatus) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010056 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010057 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010058 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010059 final Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010060 for (SdInstallArgs args : keys) {
10061 String cid = args.cid;
10062 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010063 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010064 // Delete package internally
10065 PackageRemovedInfo outInfo = new PackageRemovedInfo();
10066 synchronized (mInstallLock) {
10067 boolean res = deletePackageLI(pkgName, false,
Dianne Hackborn3aeee332010-10-02 18:56:33 -070010068 PackageManager.DONT_DELETE_DATA, outInfo, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010069 if (res) {
10070 pkgList.add(pkgName);
10071 } else {
Jeff Brown07330792010-03-30 19:57:08 -070010072 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010073 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010074 }
10075 }
10076 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070010077
10078 synchronized (mPackages) {
10079 // We didn't update the settings after removing each package;
10080 // write them now for all packages.
10081 mSettings.writeLP();
10082 }
10083
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010084 // We have to absolutely send UPDATED_MEDIA_STATUS only
10085 // after confirming that all the receivers processed the ordered
10086 // broadcast when packages get disabled, force a gc to clean things up.
10087 // and unload all the containers.
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010088 if (pkgList.size() > 0) {
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010089 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
10090 public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
10091 boolean ordered, boolean sticky) throws RemoteException {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010092 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
10093 reportStatus ? 1 : 0, 1, keys);
10094 mHandler.sendMessage(msg);
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010095 }
10096 });
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010097 } else {
10098 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
10099 reportStatus ? 1 : 0, -1, keys);
10100 mHandler.sendMessage(msg);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010101 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010102 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010103
10104 public void movePackage(final String packageName,
10105 final IPackageMoveObserver observer, final int flags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010106 mContext.enforceCallingOrSelfPermission(
10107 android.Manifest.permission.MOVE_PACKAGE, null);
10108 int returnCode = PackageManager.MOVE_SUCCEEDED;
10109 int currFlags = 0;
10110 int newFlags = 0;
10111 synchronized (mPackages) {
10112 PackageParser.Package pkg = mPackages.get(packageName);
10113 if (pkg == null) {
10114 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010115 } else {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010116 // Disable moving fwd locked apps and system packages
Kenny Root85387d72010-08-26 10:13:11 -070010117 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010118 Slog.w(TAG, "Cannot move system application");
10119 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root85387d72010-08-26 10:13:11 -070010120 } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010121 Slog.w(TAG, "Cannot move forward locked app.");
10122 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
Kenny Rootdeb11262010-08-02 11:36:21 -070010123 } else if (pkg.mOperationPending) {
10124 Slog.w(TAG, "Attempt to move package which has pending operations");
10125 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010126 } else {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010127 // Find install location first
10128 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
10129 (flags & PackageManager.MOVE_INTERNAL) != 0) {
10130 Slog.w(TAG, "Ambigous flags specified for move location.");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010131 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010132 } else {
10133 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
10134 PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
Kenny Root85387d72010-08-26 10:13:11 -070010135 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
10136 : PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010137 if (newFlags == currFlags) {
10138 Slog.w(TAG, "No move required. Trying to move to same location");
10139 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
10140 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010141 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010142 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10143 pkg.mOperationPending = true;
10144 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010145 }
10146 }
10147 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root85387d72010-08-26 10:13:11 -070010148 processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010149 } else {
10150 Message msg = mHandler.obtainMessage(INIT_COPY);
10151 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -070010152 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
10153 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
10154 pkg.applicationInfo.dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010155 msg.obj = mp;
10156 mHandler.sendMessage(msg);
10157 }
10158 }
10159 }
10160
10161 private void processPendingMove(final MoveParams mp, final int currentStatus) {
10162 // Queue up an async operation since the package deletion may take a little while.
10163 mHandler.post(new Runnable() {
10164 public void run() {
10165 mHandler.removeCallbacks(this);
10166 int returnCode = currentStatus;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010167 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
10168 int uidArr[] = null;
10169 ArrayList<String> pkgList = null;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010170 synchronized (mPackages) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010171 PackageParser.Package pkg = mPackages.get(mp.packageName);
Kenny Root85387d72010-08-26 10:13:11 -070010172 if (pkg == null) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010173 Slog.w(TAG, " Package " + mp.packageName +
10174 " doesn't exist. Aborting move");
10175 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
10176 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
10177 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
10178 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
10179 " Aborting move and returning error");
10180 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10181 } else {
10182 uidArr = new int[] { pkg.applicationInfo.uid };
10183 pkgList = new ArrayList<String>();
10184 pkgList.add(mp.packageName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010185 }
10186 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010187 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10188 // Send resources unavailable broadcast
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010189 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010190 // Update package code and resource paths
10191 synchronized (mInstallLock) {
10192 synchronized (mPackages) {
10193 PackageParser.Package pkg = mPackages.get(mp.packageName);
10194 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -070010195 if (pkg == null) {
10196 Slog.w(TAG, " Package " + mp.packageName
10197 + " doesn't exist. Aborting move");
10198 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010199 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
10200 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
10201 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
10202 " Aborting move and returning error");
10203 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10204 } else {
Kenny Root85387d72010-08-26 10:13:11 -070010205 final String oldCodePath = pkg.mPath;
10206 final String newCodePath = mp.targetArgs.getCodePath();
10207 final String newResPath = mp.targetArgs.getResourcePath();
10208 final String newNativePath = mp.targetArgs.getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -070010209
10210 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) {
10211 if (mInstaller
10212 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
10213 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10214 } else {
10215 NativeLibraryHelper.copyNativeBinariesLI(
10216 new File(newCodePath), new File(newNativePath));
10217 }
10218 } else {
10219 if (mInstaller.linkNativeLibraryDirectory(
10220 pkg.applicationInfo.dataDir, newNativePath) < 0) {
10221 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10222 }
10223 }
10224
10225 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10226 pkg.mPath = newCodePath;
10227 // Move dex files around
10228 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
10229 // Moving of dex files failed. Set
10230 // error code and abort move.
10231 pkg.mPath = pkg.mScanPath;
10232 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10233 }
10234 }
10235
10236 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010237 pkg.mScanPath = newCodePath;
10238 pkg.applicationInfo.sourceDir = newCodePath;
10239 pkg.applicationInfo.publicSourceDir = newResPath;
Kenny Root85387d72010-08-26 10:13:11 -070010240 pkg.applicationInfo.nativeLibraryDir = newNativePath;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010241 PackageSetting ps = (PackageSetting) pkg.mExtras;
10242 ps.codePath = new File(pkg.applicationInfo.sourceDir);
10243 ps.codePathString = ps.codePath.getPath();
10244 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
10245 ps.resourcePathString = ps.resourcePath.getPath();
Kenny Root0ac83f52010-08-30 15:12:24 -070010246 ps.nativeLibraryPathString = newNativePath;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010247 // Set the application info flag correctly.
10248 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
10249 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10250 } else {
10251 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10252 }
10253 ps.setFlags(pkg.applicationInfo.flags);
10254 mAppDirs.remove(oldCodePath);
10255 mAppDirs.put(newCodePath, pkg);
10256 // Persist settings
10257 mSettings.writeLP();
10258 }
10259 }
10260 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010261 }
Suchi Amalapurapu0c1285f2010-04-14 17:05:48 -070010262 // Send resources available broadcast
10263 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010264 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010265 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010266 if (returnCode != PackageManager.MOVE_SUCCEEDED){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010267 // Clean up failed installation
10268 if (mp.targetArgs != null) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010269 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010270 }
10271 } else {
10272 // Force a gc to clear things up.
10273 Runtime.getRuntime().gc();
10274 // Delete older code
10275 synchronized (mInstallLock) {
10276 mp.srcArgs.doPostDeleteLI(true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010277 }
10278 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010279
10280 // Allow more operations on this file if we didn't fail because
10281 // an operation was already pending for this package.
10282 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
10283 synchronized (mPackages) {
10284 PackageParser.Package pkg = mPackages.get(mp.packageName);
10285 if (pkg != null) {
10286 pkg.mOperationPending = false;
10287 }
10288 }
10289 }
10290
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010291 IPackageMoveObserver observer = mp.observer;
10292 if (observer != null) {
10293 try {
10294 observer.packageMoved(mp.packageName, returnCode);
10295 } catch (RemoteException e) {
10296 Log.i(TAG, "Observer no longer exists.");
10297 }
10298 }
10299 }
10300 });
10301 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070010302
10303 public boolean setInstallLocation(int loc) {
10304 mContext.enforceCallingOrSelfPermission(
10305 android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
10306 if (getInstallLocation() == loc) {
10307 return true;
10308 }
10309 if (loc == PackageHelper.APP_INSTALL_AUTO ||
10310 loc == PackageHelper.APP_INSTALL_INTERNAL ||
10311 loc == PackageHelper.APP_INSTALL_EXTERNAL) {
10312 android.provider.Settings.System.putInt(mContext.getContentResolver(),
10313 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
10314 return true;
10315 }
10316 return false;
10317 }
10318
10319 public int getInstallLocation() {
10320 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
10321 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO);
10322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323}