blob: f1a6e151e173953c230aabfbd6b9b1835901416d [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
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080019import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.app.ResolverActivity;
Kenny Root85387d72010-08-26 10:13:11 -070021import com.android.internal.content.NativeLibraryHelper;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080022import com.android.internal.content.PackageHelper;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080023import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070024import com.android.internal.util.JournaledFile;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080025import com.android.internal.util.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
Jason parksa3cdaa52011-01-13 14:15:43 -060027import org.xmlpull.v1.XmlPullParser;
28import org.xmlpull.v1.XmlPullParserException;
29import org.xmlpull.v1.XmlSerializer;
30
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;
Jason parks1125d782011-01-12 09:47:26 -060035import android.content.Context;
Jason parksa3cdaa52011-01-13 14:15:43 -060036import android.content.ComponentName;
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;
Jason parks1125d782011-01-12 09:47:26 -060041import android.content.ServiceConnection;
Jason parksa3cdaa52011-01-13 14:15:43 -060042import android.content.IntentSender.SendIntentException;
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;
Jason parks1125d782011-01-12 09:47:26 -060057import android.content.pm.PackageStats;
Jason parksa3cdaa52011-01-13 14:15:43 -060058import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
59import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
60import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
61import android.content.pm.PackageParser;
Jason parks1125d782011-01-12 09:47:26 -060062import android.content.pm.PermissionInfo;
Jason parksa3cdaa52011-01-13 14:15:43 -060063import android.content.pm.PermissionGroupInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.content.pm.ProviderInfo;
65import android.content.pm.ResolveInfo;
66import android.content.pm.ServiceInfo;
67import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.net.Uri;
69import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070070import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080072import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080074import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070075import android.os.Looper;
76import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.Parcel;
Jason parksa3cdaa52011-01-13 14:15:43 -060078import android.os.RemoteException;
79import android.os.Environment;
80import android.os.FileObserver;
81import android.os.FileUtils;
82import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.ParcelFileDescriptor;
84import android.os.Process;
85import android.os.ServiceManager;
86import android.os.SystemClock;
87import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080088import android.security.SystemKeyStore;
Jason parksa3cdaa52011-01-13 14:15:43 -060089import android.util.*;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.view.Display;
91import android.view.WindowManager;
92
Kenny Root9f306d72010-09-26 11:19:47 -070093import java.io.BufferedOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import java.io.File;
95import java.io.FileDescriptor;
96import java.io.FileInputStream;
97import java.io.FileNotFoundException;
98import java.io.FileOutputStream;
99import java.io.FileReader;
100import java.io.FilenameFilter;
101import java.io.IOException;
102import java.io.InputStream;
103import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800104import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800105import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.ArrayList;
107import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700108import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.util.Collections;
110import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800111import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.util.Enumeration;
113import java.util.HashMap;
114import java.util.HashSet;
115import java.util.Iterator;
116import java.util.List;
117import java.util.Map;
118import java.util.Set;
119import java.util.zip.ZipEntry;
120import java.util.zip.ZipFile;
121import java.util.zip.ZipOutputStream;
122
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700123/**
124 * Keep track of all those .apks everywhere.
125 *
126 * This is very central to the platform's security; please run the unit
127 * tests whenever making modifications here:
128 *
129mmm frameworks/base/tests/AndroidTests
130adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
131adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
132 *
133 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134class PackageManagerService extends IPackageManager.Stub {
135 private static final String TAG = "PackageManager";
136 private static final boolean DEBUG_SETTINGS = false;
137 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800138 private static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800139 private static final boolean DEBUG_INSTALL = false;
Dianne Hackborne7f97212011-02-24 14:40:20 -0800140 private static final boolean DEBUG_STOPPED = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
142 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
143 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400144 private static final int LOG_UID = Process.LOG_UID;
Nick Pellycd0e8392010-10-13 17:25:24 -0700145 private static final int NFC_UID = Process.NFC_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private static final int FIRST_APPLICATION_UID =
147 Process.FIRST_APPLICATION_UID;
148 private static final int MAX_APPLICATION_UIDS = 1000;
149
150 private static final boolean SHOW_INFO = false;
151
152 private static final boolean GET_CERTIFICATES = true;
153
154 private static final int REMOVE_EVENTS =
155 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
156 private static final int ADD_EVENTS =
157 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
158
159 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800160 // Suffix used during package installation when copying/moving
161 // package apks to install directory.
162 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -0800164 /**
165 * Indicates the state of installation. Used by PackageManager to
166 * figure out incomplete installations. Say a package is being installed
167 * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
168 * the package installation is successful or unsuccesful lin which case
169 * the PackageManager will no longer maintain state information associated
170 * with the package. If some exception(like device freeze or battery being
171 * pulled out) occurs during installation of a package, the PackageManager
172 * needs this information to clean up the previously failed installation.
173 */
174 private static final int PKG_INSTALL_INCOMPLETE = 0;
175 private static final int PKG_INSTALL_COMPLETE = 1;
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 static final int SCAN_MONITOR = 1<<0;
178 static final int SCAN_NO_DEX = 1<<1;
179 static final int SCAN_FORCE_DEX = 1<<2;
180 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800181 static final int SCAN_NEW_INSTALL = 1<<4;
182 static final int SCAN_NO_PATHS = 1<<5;
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700183 static final int SCAN_UPDATE_TIME = 1<<6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700185 static final int REMOVE_CHATTY = 1<<16;
Kenny Root11128572010-10-11 10:51:32 -0700186
187 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
188
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800189 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
Kenny Root11128572010-10-11 10:51:32 -0700190 DEFAULT_CONTAINER_PACKAGE,
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800191 "com.android.defcontainer.DefaultContainerService");
Kenny Rootc78a8072010-07-27 15:18:38 -0700192
Kenny Root85387d72010-08-26 10:13:11 -0700193 private static final String LIB_DIR_NAME = "lib";
194
Kenny Rootc78a8072010-07-27 15:18:38 -0700195 static final String mTempContainerPrefix = "smdl2tmp";
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
198 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700199 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Dianne Hackborn851a5412009-05-08 12:06:44 -0700201 final int mSdkVersion = Build.VERSION.SDK_INT;
202 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
203 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 final Context mContext;
206 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700207 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 final DisplayMetrics mMetrics;
209 final int mDefParseFlags;
210 final String[] mSeparateProcesses;
211
212 // This is where all application persistent data goes.
213 final File mAppDataDir;
214
215 // This is the object monitoring the framework dir.
216 final FileObserver mFrameworkInstallObserver;
217
218 // This is the object monitoring the system app dir.
219 final FileObserver mSystemInstallObserver;
220
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700221 // This is the object monitoring the system app dir.
222 final FileObserver mVendorInstallObserver;
223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 // This is the object monitoring mAppInstallDir.
225 final FileObserver mAppInstallObserver;
226
227 // This is the object monitoring mDrmAppPrivateInstallDir.
228 final FileObserver mDrmAppInstallObserver;
229
230 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
231 // LOCK HELD. Can be called with mInstallLock held.
232 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 final File mFrameworkDir;
235 final File mSystemAppDir;
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700236 final File mVendorAppDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700238 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239
240 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
241 // apps.
242 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // Lock for state used when installing and doing other long running
247 // operations. Methods that must be called with this lock held have
248 // the prefix "LI".
249 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 // These are the directories in the 3rd party applications installed dir
252 // that we have currently loaded packages from. Keys are the application's
253 // installed zip file (absolute codePath), and values are Package.
254 final HashMap<String, PackageParser.Package> mAppDirs =
255 new HashMap<String, PackageParser.Package>();
256
257 // Information for the parser to write more useful error messages.
258 File mScanningPath;
259 int mLastScanError;
260
261 final int[] mOutPermissions = new int[3];
262
263 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 // Keys are String (package name), values are Package. This also serves
266 // as the lock for the global state. Methods that must be called with
267 // this lock held have the prefix "LP".
268 final HashMap<String, PackageParser.Package> mPackages =
269 new HashMap<String, PackageParser.Package>();
270
271 final Settings mSettings;
272 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
275 int[] mGlobalGids;
276
277 // These are the built-in uid -> permission mappings that were read from the
278 // etc/permissions.xml file.
279 final SparseArray<HashSet<String>> mSystemPermissions =
280 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 // These are the built-in shared libraries that were read from the
283 // etc/permissions.xml file.
284 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800285
Dianne Hackborn49237342009-08-27 20:08:01 -0700286 // Temporary for building the final shared libraries for an .apk.
287 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800288
Dianne Hackborn49237342009-08-27 20:08:01 -0700289 // These are the features this devices supports that were read from the
290 // etc/permissions.xml file.
291 final HashMap<String, FeatureInfo> mAvailableFeatures =
292 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 // All available activities, for your resolving pleasure.
295 final ActivityIntentResolver mActivities =
296 new ActivityIntentResolver();
297
298 // All available receivers, for your resolving pleasure.
299 final ActivityIntentResolver mReceivers =
300 new ActivityIntentResolver();
301
302 // All available services, for your resolving pleasure.
303 final ServiceIntentResolver mServices = new ServiceIntentResolver();
304
305 // Keys are String (provider class name), values are Provider.
306 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
307 new HashMap<ComponentName, PackageParser.Provider>();
308
309 // Mapping from provider base names (first directory in content URI codePath)
310 // to the provider information.
311 final HashMap<String, PackageParser.Provider> mProviders =
312 new HashMap<String, PackageParser.Provider>();
313
314 // Mapping from instrumentation class names to info about them.
315 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
316 new HashMap<ComponentName, PackageParser.Instrumentation>();
317
318 // Mapping from permission names to info about them.
319 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
320 new HashMap<String, PackageParser.PermissionGroup>();
321
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800322 // Packages whose data we have transfered into another package, thus
323 // should no longer exist.
324 final HashSet<String> mTransferedPackages = new HashSet<String>();
325
Dianne Hackborn854060af2009-07-09 18:14:31 -0700326 // Broadcast actions that are only available to the system.
327 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 boolean mSystemReady;
330 boolean mSafeMode;
331 boolean mHasSystemUidErrors;
332
333 ApplicationInfo mAndroidApplication;
334 final ActivityInfo mResolveActivity = new ActivityInfo();
335 final ResolveInfo mResolveInfo = new ResolveInfo();
336 ComponentName mResolveComponentName;
337 PackageParser.Package mPlatformPackage;
338
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700339 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800340 final HashMap<String, ArrayList<String>> mPendingBroadcasts
341 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800342 // Service Connection to remote media container service to copy
343 // package uri's from external media onto secure containers
344 // or internal storage.
345 private IMediaContainerService mContainerService = null;
346
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700347 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800348 static final int MCS_BOUND = 3;
349 static final int END_COPY = 4;
350 static final int INIT_COPY = 5;
351 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800352 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800353 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800354 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800355 static final int MCS_RECONNECT = 10;
356 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700357 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700358 static final int WRITE_SETTINGS = 13;
Dianne Hackborne7f97212011-02-24 14:40:20 -0800359 static final int WRITE_STOPPED_PACKAGES = 14;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700360
361 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800362
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700363 // Delay time in millisecs
364 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800365 final private DefaultContainerConnection mDefContainerConn =
366 new DefaultContainerConnection();
367 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800368 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800369 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800370 IMediaContainerService imcs =
371 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800372 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800373 }
374
375 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800376 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800377 }
378 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700379
Christopher Tate1bb69062010-02-19 17:02:12 -0800380 // Recordkeeping of restore-after-install operations that are currently in flight
381 // between the Package Manager and the Backup Manager
382 class PostInstallData {
383 public InstallArgs args;
384 public PackageInstalledInfo res;
385
386 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
387 args = _a;
388 res = _r;
389 }
390 };
391 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
392 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
393
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700394 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800395 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800396 final ArrayList<HandlerParams> mPendingInstalls =
397 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800398
399 private boolean connectToService() {
400 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
401 " DefaultContainerService");
402 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700403 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800404 if (mContext.bindService(service, mDefContainerConn,
405 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700406 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800407 mBound = true;
408 return true;
409 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700410 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800411 return false;
412 }
413
414 private void disconnectService() {
415 mContainerService = null;
416 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700417 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800418 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700419 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800420 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800421
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700422 PackageHandler(Looper looper) {
423 super(looper);
424 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700425
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700426 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700427 try {
428 doHandleMessage(msg);
429 } finally {
430 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
431 }
432 }
433
434 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700435 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800436 case INIT_COPY: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800437 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800438 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800439 int idx = mPendingInstalls.size();
440 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
441 // If a bind was already initiated we dont really
442 // need to do anything. The pending install
443 // will be processed later on.
444 if (!mBound) {
445 // If this is the only one pending we might
446 // have to bind to the service again.
447 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800448 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800449 params.serviceError();
450 return;
451 } else {
452 // Once we bind to the service, the first
453 // pending request will be processed.
454 mPendingInstalls.add(idx, params);
455 }
456 } else {
457 mPendingInstalls.add(idx, params);
458 // Already bound to the service. Just make
459 // sure we trigger off processing the first request.
460 if (idx == 0) {
461 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800462 }
463 }
464 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800465 }
466 case MCS_BOUND: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800467 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800468 if (msg.obj != null) {
469 mContainerService = (IMediaContainerService) msg.obj;
470 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800471 if (mContainerService == null) {
472 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800473 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800474 for (HandlerParams params : mPendingInstalls) {
475 mPendingInstalls.remove(0);
476 // Indicate service bind error
477 params.serviceError();
478 }
479 mPendingInstalls.clear();
480 } else if (mPendingInstalls.size() > 0) {
481 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800482 if (params != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800483 params.startCopy();
484 }
485 } else {
486 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800487 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800488 }
489 break;
490 }
491 case MCS_RECONNECT : {
492 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
493 if (mPendingInstalls.size() > 0) {
494 if (mBound) {
495 disconnectService();
496 }
497 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800498 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800499 for (HandlerParams params : mPendingInstalls) {
500 mPendingInstalls.remove(0);
501 // Indicate service bind error
502 params.serviceError();
503 }
504 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800505 }
506 }
507 break;
508 }
509 case MCS_UNBIND : {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800510 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
511 // Delete pending install
512 if (mPendingInstalls.size() > 0) {
513 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800514 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800515 if (mPendingInstalls.size() == 0) {
516 if (mBound) {
517 disconnectService();
518 }
519 } else {
520 // There are more pending requests in queue.
521 // Just post MCS_BOUND message to trigger processing
522 // of next pending install.
523 mHandler.sendEmptyMessage(MCS_BOUND);
524 }
525 break;
526 }
527 case MCS_GIVE_UP: {
528 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
529 HandlerParams params = mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800530 break;
531 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700532 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800533 String packages[];
534 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700535 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700536 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700537 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700538 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800539 if (mPendingBroadcasts == null) {
540 return;
541 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700542 size = mPendingBroadcasts.size();
543 if (size <= 0) {
544 // Nothing to be done. Just return
545 return;
546 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800547 packages = new String[size];
548 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700549 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800550 Iterator<HashMap.Entry<String, ArrayList<String>>>
551 it = mPendingBroadcasts.entrySet().iterator();
552 int i = 0;
553 while (it.hasNext() && i < size) {
554 HashMap.Entry<String, ArrayList<String>> ent = it.next();
555 packages[i] = ent.getKey();
556 components[i] = ent.getValue();
557 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700558 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800559 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700560 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800561 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700562 mPendingBroadcasts.clear();
563 }
564 // Send broadcasts
565 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800566 sendPackageChangedBroadcast(packages[i], true,
Jason parksa3cdaa52011-01-13 14:15:43 -0600567 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700568 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700569 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700570 break;
571 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800572 case START_CLEANING_PACKAGE: {
573 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700574 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800575 synchronized (mPackages) {
576 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
577 mSettings.mPackagesToBeCleaned.add(packageName);
578 }
579 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700580 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800581 startCleaningPackages();
582 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800583 case POST_INSTALL: {
584 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
585 PostInstallData data = mRunningInstalls.get(msg.arg1);
586 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700587 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800588
589 if (data != null) {
590 InstallArgs args = data.args;
591 PackageInstalledInfo res = data.res;
592
593 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700594 res.removedInfo.sendBroadcast(false, true);
Christopher Tate1bb69062010-02-19 17:02:12 -0800595 Bundle extras = new Bundle(1);
596 extras.putInt(Intent.EXTRA_UID, res.uid);
597 final boolean update = res.removedInfo.removedPackage != null;
598 if (update) {
599 extras.putBoolean(Intent.EXTRA_REPLACING, true);
600 }
601 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
602 res.pkg.applicationInfo.packageName,
Dianne Hackborne7f97212011-02-24 14:40:20 -0800603 extras, null, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800604 if (update) {
605 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
606 res.pkg.applicationInfo.packageName,
Dianne Hackborne7f97212011-02-24 14:40:20 -0800607 extras, null, null);
608 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
609 null, null,
610 res.pkg.applicationInfo.packageName, null);
Christopher Tate1bb69062010-02-19 17:02:12 -0800611 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -0700612 if (res.removedInfo.args != null) {
613 // Remove the replaced package's older resources safely now
614 deleteOld = true;
615 }
616 }
617 // Force a gc to clear up things
618 Runtime.getRuntime().gc();
619 // We delete after a gc for applications on sdcard.
620 if (deleteOld) {
621 synchronized (mInstallLock) {
622 res.removedInfo.args.doPostDeleteLI(true);
623 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800624 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800625 if (args.observer != null) {
626 try {
627 args.observer.packageInstalled(res.name, res.returnCode);
628 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800629 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800630 }
631 }
632 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800633 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800634 }
635 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700636 case UPDATED_MEDIA_STATUS: {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -0700637 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS");
638 boolean reportStatus = msg.arg1 == 1;
639 boolean doGc = msg.arg2 == 1;
640 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc);
641 if (doGc) {
642 // Force a gc to clear up stale containers.
643 Runtime.getRuntime().gc();
644 }
645 if (msg.obj != null) {
646 Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
647 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
648 // Unload containers
649 unloadAllContainers(args);
650 }
651 if (reportStatus) {
652 try {
653 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back");
654 PackageHelper.getMountService().finishMediaUpdate();
655 } catch (RemoteException e) {
656 Log.e(TAG, "MountService not running?");
657 }
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700658 }
659 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700660 case WRITE_SETTINGS: {
661 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
662 synchronized (mPackages) {
663 removeMessages(WRITE_SETTINGS);
Dianne Hackborne7f97212011-02-24 14:40:20 -0800664 removeMessages(WRITE_STOPPED_PACKAGES);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700665 mSettings.writeLP();
666 }
667 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
668 } break;
Dianne Hackborne7f97212011-02-24 14:40:20 -0800669 case WRITE_STOPPED_PACKAGES: {
670 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
671 synchronized (mPackages) {
672 removeMessages(WRITE_STOPPED_PACKAGES);
673 mSettings.writeStoppedLP();
674 }
675 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
676 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700677 }
678 }
679 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800680
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700681 void scheduleWriteSettingsLocked() {
682 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
683 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
684 }
685 }
686
Dianne Hackborne7f97212011-02-24 14:40:20 -0800687 void scheduleWriteStoppedPackagesLocked() {
688 if (!mHandler.hasMessages(WRITE_STOPPED_PACKAGES)) {
689 mHandler.sendEmptyMessageDelayed(WRITE_STOPPED_PACKAGES, WRITE_SETTINGS_DELAY);
690 }
691 }
692
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800693 static boolean installOnSd(int flags) {
694 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700695 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800696 return false;
697 }
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700698 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
699 return true;
700 }
701 return false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800702 }
703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 public static final IPackageManager main(Context context, boolean factoryTest) {
705 PackageManagerService m = new PackageManagerService(context, factoryTest);
706 ServiceManager.addService("package", m);
707 return m;
708 }
709
710 static String[] splitString(String str, char sep) {
711 int count = 1;
712 int i = 0;
713 while ((i=str.indexOf(sep, i)) >= 0) {
714 count++;
715 i++;
716 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 String[] res = new String[count];
719 i=0;
720 count = 0;
721 int lastI=0;
722 while ((i=str.indexOf(sep, i)) >= 0) {
723 res[count] = str.substring(lastI, i);
724 count++;
725 i++;
726 lastI = i;
727 }
728 res[count] = str.substring(lastI, str.length());
729 return res;
730 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800733 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800737 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 mContext = context;
741 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700742 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 mMetrics = new DisplayMetrics();
744 mSettings = new Settings();
745 mSettings.addSharedUserLP("android.uid.system",
746 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
747 mSettings.addSharedUserLP("android.uid.phone",
748 MULTIPLE_APPLICATION_UIDS
749 ? RADIO_UID : FIRST_APPLICATION_UID,
750 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400751 mSettings.addSharedUserLP("android.uid.log",
752 MULTIPLE_APPLICATION_UIDS
753 ? LOG_UID : FIRST_APPLICATION_UID,
754 ApplicationInfo.FLAG_SYSTEM);
Nick Pellycd0e8392010-10-13 17:25:24 -0700755 mSettings.addSharedUserLP("android.uid.nfc",
756 MULTIPLE_APPLICATION_UIDS
757 ? NFC_UID : FIRST_APPLICATION_UID,
758 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759
760 String separateProcesses = SystemProperties.get("debug.separate_processes");
761 if (separateProcesses != null && separateProcesses.length() > 0) {
762 if ("*".equals(separateProcesses)) {
763 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
764 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800765 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 } else {
767 mDefParseFlags = 0;
768 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800769 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 + separateProcesses);
771 }
772 } else {
773 mDefParseFlags = 0;
774 mSeparateProcesses = null;
775 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 Installer installer = new Installer();
778 // Little hacky thing to check if installd is here, to determine
779 // whether we are running on the simulator and thus need to take
780 // care of building the /data file structure ourself.
781 // (apparently the sim now has a working installer)
782 if (installer.ping() && Process.supportsProcesses()) {
783 mInstaller = installer;
784 } else {
785 mInstaller = null;
786 }
787
788 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
789 Display d = wm.getDefaultDisplay();
790 d.getMetrics(mMetrics);
791
792 synchronized (mInstallLock) {
793 synchronized (mPackages) {
794 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700795 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 File dataDir = Environment.getDataDirectory();
798 mAppDataDir = new File(dataDir, "data");
799 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
800
801 if (mInstaller == null) {
802 // Make sure these dirs exist, when we are running in
803 // the simulator.
804 // Make a wide-open directory for random misc stuff.
805 File miscDir = new File(dataDir, "misc");
806 miscDir.mkdirs();
807 mAppDataDir.mkdirs();
808 mDrmAppPrivateInstallDir.mkdirs();
809 }
810
811 readPermissions();
812
813 mRestoredSettings = mSettings.readLP();
814 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800815
816 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800818
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800819 // Set flag to monitor and not change apk file paths when
820 // scanning install directories.
821 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700822 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800823 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800824 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700825 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700830 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700833 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 /**
836 * Out of paranoia, ensure that everything in the boot class
837 * path has been dexed.
838 */
839 String bootClassPath = System.getProperty("java.boot.class.path");
840 if (bootClassPath != null) {
841 String[] paths = splitString(bootClassPath, ':');
842 for (int i=0; i<paths.length; i++) {
843 try {
844 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
845 libFiles.add(paths[i]);
846 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700847 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 }
849 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800850 Slog.w(TAG, "Boot class path not found: " + paths[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800852 Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 }
854 }
855 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800856 Slog.w(TAG, "No BOOTCLASSPATH found!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 /**
860 * Also ensure all external libraries have had dexopt run on them.
861 */
862 if (mSharedLibraries.size() > 0) {
863 Iterator<String> libs = mSharedLibraries.values().iterator();
864 while (libs.hasNext()) {
865 String lib = libs.next();
866 try {
867 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
868 libFiles.add(lib);
869 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700870 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 }
872 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800873 Slog.w(TAG, "Library not found: " + lib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800875 Slog.w(TAG, "Exception reading library: " + lib, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 }
877 }
878 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 // Gross hack for now: we know this file doesn't contain any
881 // code, so don't dexopt it to avoid the resulting log spew.
882 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 /**
885 * And there are a number of commands implemented in Java, which
886 * we currently need to do the dexopt on so that they can be
887 * run from a non-root shell.
888 */
889 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700890 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 for (int i=0; i<frameworkFiles.length; i++) {
892 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
893 String path = libPath.getPath();
894 // Skip the file if we alrady did it.
895 if (libFiles.contains(path)) {
896 continue;
897 }
898 // Skip the file if it is not a type we want to dexopt.
899 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
900 continue;
901 }
902 try {
903 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
904 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700905 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 }
907 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800908 Slog.w(TAG, "Jar not found: " + path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800910 Slog.w(TAG, "Exception reading jar: " + path, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 }
912 }
913 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800914
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700915 if (didDexOpt) {
916 // If we had to do a dexopt of one of the previous
917 // things, then something on the system has changed.
918 // Consider this significant, and wipe away all other
919 // existing dexopt files to ensure we don't leave any
920 // dangling around.
921 String[] files = mDalvikCacheDir.list();
922 if (files != null) {
923 for (int i=0; i<files.length; i++) {
924 String fn = files[i];
925 if (fn.startsWith("data@app@")
926 || fn.startsWith("data@app-private@")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800927 Slog.i(TAG, "Pruning dalvik file: " + fn);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700928 (new File(mDalvikCacheDir, fn)).delete();
929 }
930 }
931 }
932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800934
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800935 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 mFrameworkInstallObserver = new AppDirObserver(
937 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
938 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700939 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
940 | PackageParser.PARSE_IS_SYSTEM_DIR,
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700941 scanMode | SCAN_NO_DEX, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800942
943 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
945 mSystemInstallObserver = new AppDirObserver(
946 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
947 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700948 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700949 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800950
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700951 // Collect all vendor packages.
952 mVendorAppDir = new File("/vendor/app");
953 mVendorInstallObserver = new AppDirObserver(
954 mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
955 mVendorInstallObserver.startWatching();
956 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
Dianne Hackborn78d6883692010-10-07 01:12:46 -0700957 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
Dianne Hackborn3b4bac72010-09-20 11:37:52 -0700958
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800959 if (mInstaller != null) {
960 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
961 mInstaller.moveFiles();
962 }
963
964 // Prune any system packages that no longer exist.
965 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
966 while (psit.hasNext()) {
967 PackageSetting ps = psit.next();
968 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800969 && !mPackages.containsKey(ps.name)
970 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800971 psit.remove();
972 String msg = "System package " + ps.name
973 + " no longer exists; wiping its data";
974 reportSettingsProblem(Log.WARN, msg);
975 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -0800976 mInstaller.remove(ps.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800977 }
978 }
979 }
980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 mAppInstallDir = new File(dataDir, "app");
982 if (mInstaller == null) {
983 // Make sure these dirs exist, when we are running in
984 // the simulator.
985 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
986 }
987 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800988 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 //clean up list
990 for(int i = 0; i < deletePkgsList.size(); i++) {
991 //clean up here
992 cleanupInstallFailedPackage(deletePkgsList.get(i));
993 }
994 //delete tmp files
995 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800996
997 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 SystemClock.uptimeMillis());
999 mAppInstallObserver = new AppDirObserver(
1000 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
1001 mAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001002 scanDirLI(mAppInstallDir, 0, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003
1004 mDrmAppInstallObserver = new AppDirObserver(
1005 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
1006 mDrmAppInstallObserver.startWatching();
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001007 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
1008 scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001010 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001012 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 + ((SystemClock.uptimeMillis()-startTime)/1000f)
1014 + " seconds");
1015
Dianne Hackbornf22221f2010-04-05 18:35:42 -07001016 // If the platform SDK has changed since the last time we booted,
1017 // we need to re-grant app permission to catch any new ones that
1018 // appear. This is really a hack, and means that apps can in some
1019 // cases get permissions that the user didn't initially explicitly
1020 // allow... it would be nice to have some better way to handle
1021 // this situation.
1022 final boolean regrantPermissions = mSettings.mInternalSdkPlatform
1023 != mSdkVersion;
1024 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
1025 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion
1026 + "; regranting permissions for internal storage");
1027 mSettings.mInternalSdkPlatform = mSdkVersion;
1028
Dianne Hackborn92cfa102010-04-28 11:00:44 -07001029 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030
1031 mSettings.writeLP();
1032
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001033 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 // Now after opening every single application zip, make sure they
1037 // are all flushed. Not really needed, but keeps things nice and
1038 // tidy.
1039 Runtime.getRuntime().gc();
1040 } // synchronized (mPackages)
1041 } // synchronized (mInstallLock)
1042 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 @Override
1045 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
1046 throws RemoteException {
1047 try {
1048 return super.onTransact(code, data, reply, flags);
1049 } catch (RuntimeException e) {
1050 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001051 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 }
1053 throw e;
1054 }
1055 }
1056
Dianne Hackborne6620b22010-01-22 14:46:21 -08001057 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001058 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08001060 int retCode = mInstaller.remove(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001062 Slog.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -08001063 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
1065 } else {
1066 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -08001067 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 File dataDir = new File(pkg.applicationInfo.dataDir);
1069 dataDir.delete();
1070 }
Dianne Hackborne6620b22010-01-22 14:46:21 -08001071 if (ps.codePath != null) {
1072 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001073 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001074 }
1075 }
1076 if (ps.resourcePath != null) {
1077 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001078 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001079 }
1080 }
1081 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 }
1083
1084 void readPermissions() {
1085 // Read permissions from .../etc/permission directory.
1086 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1087 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001088 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 return;
1090 }
1091 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001092 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 return;
1094 }
1095
1096 // Iterate over the files in the directory and scan .xml files
1097 for (File f : libraryDir.listFiles()) {
1098 // We'll read platform.xml last
1099 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1100 continue;
1101 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001104 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 continue;
1106 }
1107 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001108 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 continue;
1110 }
1111
1112 readPermissionsFromXml(f);
1113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1116 final File permFile = new File(Environment.getRootDirectory(),
1117 "etc/permissions/platform.xml");
1118 readPermissionsFromXml(permFile);
1119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001120
1121 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 FileReader permReader = null;
1123 try {
1124 permReader = new FileReader(permFile);
1125 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001126 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 return;
1128 }
1129
1130 try {
1131 XmlPullParser parser = Xml.newPullParser();
1132 parser.setInput(permReader);
1133
1134 XmlUtils.beginDocument(parser, "permissions");
1135
1136 while (true) {
1137 XmlUtils.nextElement(parser);
1138 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1139 break;
1140 }
1141
1142 String name = parser.getName();
1143 if ("group".equals(name)) {
1144 String gidStr = parser.getAttributeValue(null, "gid");
1145 if (gidStr != null) {
1146 int gid = Integer.parseInt(gidStr);
1147 mGlobalGids = appendInt(mGlobalGids, gid);
1148 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001149 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 + parser.getPositionDescription());
1151 }
1152
1153 XmlUtils.skipCurrentTag(parser);
1154 continue;
1155 } else if ("permission".equals(name)) {
1156 String perm = parser.getAttributeValue(null, "name");
1157 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001158 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 + parser.getPositionDescription());
1160 XmlUtils.skipCurrentTag(parser);
1161 continue;
1162 }
1163 perm = perm.intern();
1164 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 } else if ("assign-permission".equals(name)) {
1167 String perm = parser.getAttributeValue(null, "name");
1168 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001169 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 + parser.getPositionDescription());
1171 XmlUtils.skipCurrentTag(parser);
1172 continue;
1173 }
1174 String uidStr = parser.getAttributeValue(null, "uid");
1175 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001176 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 + parser.getPositionDescription());
1178 XmlUtils.skipCurrentTag(parser);
1179 continue;
1180 }
1181 int uid = Process.getUidForName(uidStr);
1182 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001183 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 + uidStr + "\" at "
1185 + parser.getPositionDescription());
1186 XmlUtils.skipCurrentTag(parser);
1187 continue;
1188 }
1189 perm = perm.intern();
1190 HashSet<String> perms = mSystemPermissions.get(uid);
1191 if (perms == null) {
1192 perms = new HashSet<String>();
1193 mSystemPermissions.put(uid, perms);
1194 }
1195 perms.add(perm);
1196 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 } else if ("library".equals(name)) {
1199 String lname = parser.getAttributeValue(null, "name");
1200 String lfile = parser.getAttributeValue(null, "file");
1201 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001202 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 + parser.getPositionDescription());
1204 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001205 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 + parser.getPositionDescription());
1207 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001208 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001209 mSharedLibraries.put(lname, lfile);
1210 }
1211 XmlUtils.skipCurrentTag(parser);
1212 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001213
Dianne Hackborn49237342009-08-27 20:08:01 -07001214 } else if ("feature".equals(name)) {
1215 String fname = parser.getAttributeValue(null, "name");
1216 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001217 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001218 + parser.getPositionDescription());
1219 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001220 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001221 FeatureInfo fi = new FeatureInfo();
1222 fi.name = fname;
1223 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 XmlUtils.skipCurrentTag(parser);
1226 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 } else {
1229 XmlUtils.skipCurrentTag(parser);
1230 continue;
1231 }
1232
1233 }
Brian Carlstromfd9ddd12010-11-04 11:24:58 -07001234 permReader.close();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001236 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001238 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 }
1240 }
1241
1242 void readPermission(XmlPullParser parser, String name)
1243 throws IOException, XmlPullParserException {
1244
1245 name = name.intern();
1246
1247 BasePermission bp = mSettings.mPermissions.get(name);
1248 if (bp == null) {
1249 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1250 mSettings.mPermissions.put(name, bp);
1251 }
1252 int outerDepth = parser.getDepth();
1253 int type;
1254 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1255 && (type != XmlPullParser.END_TAG
1256 || parser.getDepth() > outerDepth)) {
1257 if (type == XmlPullParser.END_TAG
1258 || type == XmlPullParser.TEXT) {
1259 continue;
1260 }
1261
1262 String tagName = parser.getName();
1263 if ("group".equals(tagName)) {
1264 String gidStr = parser.getAttributeValue(null, "gid");
1265 if (gidStr != null) {
1266 int gid = Process.getGidForName(gidStr);
1267 bp.gids = appendInt(bp.gids, gid);
1268 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001269 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 + parser.getPositionDescription());
1271 }
1272 }
1273 XmlUtils.skipCurrentTag(parser);
1274 }
1275 }
1276
1277 static int[] appendInt(int[] cur, int val) {
1278 if (cur == null) {
1279 return new int[] { val };
1280 }
1281 final int N = cur.length;
1282 for (int i=0; i<N; i++) {
1283 if (cur[i] == val) {
1284 return cur;
1285 }
1286 }
1287 int[] ret = new int[N+1];
1288 System.arraycopy(cur, 0, ret, 0, N);
1289 ret[N] = val;
1290 return ret;
1291 }
1292
1293 static int[] appendInts(int[] cur, int[] add) {
1294 if (add == null) return cur;
1295 if (cur == null) return add;
1296 final int N = add.length;
1297 for (int i=0; i<N; i++) {
1298 cur = appendInt(cur, add[i]);
1299 }
1300 return cur;
1301 }
1302
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001303 static int[] removeInt(int[] cur, int val) {
1304 if (cur == null) {
1305 return null;
1306 }
1307 final int N = cur.length;
1308 for (int i=0; i<N; i++) {
1309 if (cur[i] == val) {
1310 int[] ret = new int[N-1];
1311 if (i > 0) {
1312 System.arraycopy(cur, 0, ret, 0, i);
1313 }
1314 if (i < (N-1)) {
Jeff Brown8c8bb8b2010-04-20 17:21:47 -07001315 System.arraycopy(cur, i + 1, ret, i, N - i - 1);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001316 }
1317 return ret;
1318 }
1319 }
1320 return cur;
1321 }
1322
1323 static int[] removeInts(int[] cur, int[] rem) {
1324 if (rem == null) return cur;
1325 if (cur == null) return cur;
1326 final int N = rem.length;
1327 for (int i=0; i<N; i++) {
1328 cur = removeInt(cur, rem[i]);
1329 }
1330 return cur;
1331 }
1332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001334 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1335 // The package has been uninstalled but has retained data and resources.
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001336 return PackageParser.generatePackageInfo(p, null, flags, 0, 0);
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 final PackageSetting ps = (PackageSetting)p.mExtras;
1339 if (ps == null) {
1340 return null;
1341 }
1342 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07001343 return PackageParser.generatePackageInfo(p, gp.gids, flags,
1344 ps.firstInstallTime, ps.lastUpdateTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 }
1346
1347 public PackageInfo getPackageInfo(String packageName, int flags) {
1348 synchronized (mPackages) {
1349 PackageParser.Package p = mPackages.get(packageName);
1350 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001351 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 + ": " + p);
1353 if (p != null) {
1354 return generatePackageInfo(p, flags);
1355 }
1356 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1357 return generatePackageInfoFromSettingsLP(packageName, flags);
1358 }
1359 }
1360 return null;
1361 }
1362
Dianne Hackborn47096932010-02-11 15:57:09 -08001363 public String[] currentToCanonicalPackageNames(String[] names) {
1364 String[] out = new String[names.length];
1365 synchronized (mPackages) {
1366 for (int i=names.length-1; i>=0; i--) {
1367 PackageSetting ps = mSettings.mPackages.get(names[i]);
1368 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1369 }
1370 }
1371 return out;
1372 }
1373
1374 public String[] canonicalToCurrentPackageNames(String[] names) {
1375 String[] out = new String[names.length];
1376 synchronized (mPackages) {
1377 for (int i=names.length-1; i>=0; i--) {
1378 String cur = mSettings.mRenamedPackages.get(names[i]);
1379 out[i] = cur != null ? cur : names[i];
1380 }
1381 }
1382 return out;
1383 }
1384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 public int getPackageUid(String packageName) {
1386 synchronized (mPackages) {
1387 PackageParser.Package p = mPackages.get(packageName);
1388 if(p != null) {
1389 return p.applicationInfo.uid;
1390 }
1391 PackageSetting ps = mSettings.mPackages.get(packageName);
1392 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1393 return -1;
1394 }
1395 p = ps.pkg;
1396 return p != null ? p.applicationInfo.uid : -1;
1397 }
1398 }
1399
1400 public int[] getPackageGids(String packageName) {
1401 synchronized (mPackages) {
1402 PackageParser.Package p = mPackages.get(packageName);
1403 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001404 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 + ": " + p);
1406 if (p != null) {
1407 final PackageSetting ps = (PackageSetting)p.mExtras;
1408 final SharedUserSetting suid = ps.sharedUser;
1409 return suid != null ? suid.gids : ps.gids;
1410 }
1411 }
1412 // stupid thing to indicate an error.
1413 return new int[0];
1414 }
1415
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001416 static final PermissionInfo generatePermissionInfo(
1417 BasePermission bp, int flags) {
1418 if (bp.perm != null) {
1419 return PackageParser.generatePermissionInfo(bp.perm, flags);
1420 }
1421 PermissionInfo pi = new PermissionInfo();
1422 pi.name = bp.name;
1423 pi.packageName = bp.sourcePackage;
1424 pi.nonLocalizedLabel = bp.name;
1425 pi.protectionLevel = bp.protectionLevel;
1426 return pi;
1427 }
1428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 public PermissionInfo getPermissionInfo(String name, int flags) {
1430 synchronized (mPackages) {
1431 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001432 if (p != null) {
1433 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
1435 return null;
1436 }
1437 }
1438
1439 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1440 synchronized (mPackages) {
1441 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1442 for (BasePermission p : mSettings.mPermissions.values()) {
1443 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001444 if (p.perm == null || p.perm.info.group == null) {
1445 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 }
1447 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001448 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1450 }
1451 }
1452 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 if (out.size() > 0) {
1455 return out;
1456 }
1457 return mPermissionGroups.containsKey(group) ? out : null;
1458 }
1459 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1462 synchronized (mPackages) {
1463 return PackageParser.generatePermissionGroupInfo(
1464 mPermissionGroups.get(name), flags);
1465 }
1466 }
1467
1468 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1469 synchronized (mPackages) {
1470 final int N = mPermissionGroups.size();
1471 ArrayList<PermissionGroupInfo> out
1472 = new ArrayList<PermissionGroupInfo>(N);
1473 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1474 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1475 }
1476 return out;
1477 }
1478 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1481 PackageSetting ps = mSettings.mPackages.get(packageName);
1482 if(ps != null) {
1483 if(ps.pkg == null) {
1484 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1485 if(pInfo != null) {
1486 return pInfo.applicationInfo;
1487 }
1488 return null;
1489 }
1490 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1491 }
1492 return null;
1493 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1496 PackageSetting ps = mSettings.mPackages.get(packageName);
1497 if(ps != null) {
1498 if(ps.pkg == null) {
1499 ps.pkg = new PackageParser.Package(packageName);
1500 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001501 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1502 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1503 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
1504 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
Kenny Root85387d72010-08-26 10:13:11 -07001505 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07001506 ps.pkg.mSetEnabled = ps.enabled;
Dianne Hackborne7f97212011-02-24 14:40:20 -08001507 ps.pkg.mSetStopped = ps.stopped;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 }
1509 return generatePackageInfo(ps.pkg, flags);
1510 }
1511 return null;
1512 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1515 synchronized (mPackages) {
1516 PackageParser.Package p = mPackages.get(packageName);
1517 if (Config.LOGV) Log.v(
1518 TAG, "getApplicationInfo " + packageName
1519 + ": " + p);
1520 if (p != null) {
1521 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001522 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 }
1524 if ("android".equals(packageName)||"system".equals(packageName)) {
1525 return mAndroidApplication;
1526 }
1527 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1528 return generateApplicationInfoFromSettingsLP(packageName, flags);
1529 }
1530 }
1531 return null;
1532 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001533
1534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1536 mContext.enforceCallingOrSelfPermission(
1537 android.Manifest.permission.CLEAR_APP_CACHE, null);
1538 // Queue up an async operation since clearing cache may take a little while.
1539 mHandler.post(new Runnable() {
1540 public void run() {
1541 mHandler.removeCallbacks(this);
1542 int retCode = -1;
1543 if (mInstaller != null) {
1544 retCode = mInstaller.freeCache(freeStorageSize);
1545 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001546 Slog.w(TAG, "Couldn't clear application caches");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 }
1548 } //end if mInstaller
1549 if (observer != null) {
1550 try {
1551 observer.onRemoveCompleted(null, (retCode >= 0));
1552 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001553 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555 }
1556 }
1557 });
1558 }
1559
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001560 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001561 mContext.enforceCallingOrSelfPermission(
1562 android.Manifest.permission.CLEAR_APP_CACHE, null);
1563 // Queue up an async operation since clearing cache may take a little while.
1564 mHandler.post(new Runnable() {
1565 public void run() {
1566 mHandler.removeCallbacks(this);
1567 int retCode = -1;
1568 if (mInstaller != null) {
1569 retCode = mInstaller.freeCache(freeStorageSize);
1570 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001571 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001572 }
1573 }
1574 if(pi != null) {
1575 try {
1576 // Callback via pending intent
1577 int code = (retCode >= 0) ? 1 : 0;
1578 pi.sendIntent(null, code, null,
1579 null, null);
1580 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001581 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001582 }
1583 }
1584 }
1585 });
1586 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1589 synchronized (mPackages) {
1590 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001591
1592 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001594 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
1596 if (mResolveComponentName.equals(component)) {
1597 return mResolveActivity;
1598 }
1599 }
1600 return null;
1601 }
1602
1603 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1604 synchronized (mPackages) {
1605 PackageParser.Activity a = mReceivers.mActivities.get(component);
1606 if (Config.LOGV) Log.v(
1607 TAG, "getReceiverInfo " + component + ": " + a);
1608 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1609 return PackageParser.generateActivityInfo(a, flags);
1610 }
1611 }
1612 return null;
1613 }
1614
1615 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1616 synchronized (mPackages) {
1617 PackageParser.Service s = mServices.mServices.get(component);
1618 if (Config.LOGV) Log.v(
1619 TAG, "getServiceInfo " + component + ": " + s);
1620 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1621 return PackageParser.generateServiceInfo(s, flags);
1622 }
1623 }
1624 return null;
1625 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001626
Dianne Hackborn361199b2010-08-30 17:42:07 -07001627 public ProviderInfo getProviderInfo(ComponentName component, int flags) {
1628 synchronized (mPackages) {
1629 PackageParser.Provider p = mProvidersByComponent.get(component);
1630 if (Config.LOGV) Log.v(
1631 TAG, "getProviderInfo " + component + ": " + p);
1632 if (p != null && mSettings.isEnabledLP(p.info, flags)) {
1633 return PackageParser.generateProviderInfo(p, flags);
1634 }
1635 }
1636 return null;
1637 }
1638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 public String[] getSystemSharedLibraryNames() {
1640 Set<String> libSet;
1641 synchronized (mPackages) {
1642 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001643 int size = libSet.size();
1644 if (size > 0) {
1645 String[] libs = new String[size];
1646 libSet.toArray(libs);
1647 return libs;
1648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001650 return null;
1651 }
1652
1653 public FeatureInfo[] getSystemAvailableFeatures() {
1654 Collection<FeatureInfo> featSet;
1655 synchronized (mPackages) {
1656 featSet = mAvailableFeatures.values();
1657 int size = featSet.size();
1658 if (size > 0) {
1659 FeatureInfo[] features = new FeatureInfo[size+1];
1660 featSet.toArray(features);
1661 FeatureInfo fi = new FeatureInfo();
1662 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1663 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1664 features[size] = fi;
1665 return features;
1666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 }
1668 return null;
1669 }
1670
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001671 public boolean hasSystemFeature(String name) {
1672 synchronized (mPackages) {
1673 return mAvailableFeatures.containsKey(name);
1674 }
1675 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 public int checkPermission(String permName, String pkgName) {
1678 synchronized (mPackages) {
1679 PackageParser.Package p = mPackages.get(pkgName);
1680 if (p != null && p.mExtras != null) {
1681 PackageSetting ps = (PackageSetting)p.mExtras;
1682 if (ps.sharedUser != null) {
1683 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1684 return PackageManager.PERMISSION_GRANTED;
1685 }
1686 } else if (ps.grantedPermissions.contains(permName)) {
1687 return PackageManager.PERMISSION_GRANTED;
1688 }
1689 }
1690 }
1691 return PackageManager.PERMISSION_DENIED;
1692 }
1693
1694 public int checkUidPermission(String permName, int uid) {
1695 synchronized (mPackages) {
1696 Object obj = mSettings.getUserIdLP(uid);
1697 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001698 GrantedPermissions gp = (GrantedPermissions)obj;
1699 if (gp.grantedPermissions.contains(permName)) {
1700 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 }
1702 } else {
1703 HashSet<String> perms = mSystemPermissions.get(uid);
1704 if (perms != null && perms.contains(permName)) {
1705 return PackageManager.PERMISSION_GRANTED;
1706 }
1707 }
1708 }
1709 return PackageManager.PERMISSION_DENIED;
1710 }
1711
1712 private BasePermission findPermissionTreeLP(String permName) {
1713 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1714 if (permName.startsWith(bp.name) &&
1715 permName.length() > bp.name.length() &&
1716 permName.charAt(bp.name.length()) == '.') {
1717 return bp;
1718 }
1719 }
1720 return null;
1721 }
1722
1723 private BasePermission checkPermissionTreeLP(String permName) {
1724 if (permName != null) {
1725 BasePermission bp = findPermissionTreeLP(permName);
1726 if (bp != null) {
1727 if (bp.uid == Binder.getCallingUid()) {
1728 return bp;
1729 }
1730 throw new SecurityException("Calling uid "
1731 + Binder.getCallingUid()
1732 + " is not allowed to add to permission tree "
1733 + bp.name + " owned by uid " + bp.uid);
1734 }
1735 }
1736 throw new SecurityException("No permission tree found for " + permName);
1737 }
1738
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001739 static boolean compareStrings(CharSequence s1, CharSequence s2) {
1740 if (s1 == null) {
1741 return s2 == null;
1742 }
1743 if (s2 == null) {
1744 return false;
1745 }
1746 if (s1.getClass() != s2.getClass()) {
1747 return false;
1748 }
1749 return s1.equals(s2);
1750 }
1751
1752 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
1753 if (pi1.icon != pi2.icon) return false;
Adam Powell81cd2e92010-04-21 16:35:18 -07001754 if (pi1.logo != pi2.logo) return false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001755 if (pi1.protectionLevel != pi2.protectionLevel) return false;
1756 if (!compareStrings(pi1.name, pi2.name)) return false;
1757 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
1758 // We'll take care of setting this one.
1759 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
1760 // These are not currently stored in settings.
1761 //if (!compareStrings(pi1.group, pi2.group)) return false;
1762 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
1763 //if (pi1.labelRes != pi2.labelRes) return false;
1764 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
1765 return true;
1766 }
1767
1768 boolean addPermissionLocked(PermissionInfo info, boolean async) {
1769 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1770 throw new SecurityException("Label must be specified in permission");
1771 }
1772 BasePermission tree = checkPermissionTreeLP(info.name);
1773 BasePermission bp = mSettings.mPermissions.get(info.name);
1774 boolean added = bp == null;
1775 boolean changed = true;
1776 if (added) {
1777 bp = new BasePermission(info.name, tree.sourcePackage,
1778 BasePermission.TYPE_DYNAMIC);
1779 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1780 throw new SecurityException(
1781 "Not allowed to modify non-dynamic permission "
1782 + info.name);
1783 } else {
1784 if (bp.protectionLevel == info.protectionLevel
1785 && bp.perm.owner.equals(tree.perm.owner)
1786 && bp.uid == tree.uid
1787 && comparePermissionInfos(bp.perm.info, info)) {
1788 changed = false;
1789 }
1790 }
1791 bp.protectionLevel = info.protectionLevel;
1792 bp.perm = new PackageParser.Permission(tree.perm.owner,
1793 new PermissionInfo(info));
1794 bp.perm.info.packageName = tree.perm.info.packageName;
1795 bp.uid = tree.uid;
1796 if (added) {
1797 mSettings.mPermissions.put(info.name, bp);
1798 }
1799 if (changed) {
1800 if (!async) {
1801 mSettings.writeLP();
1802 } else {
1803 scheduleWriteSettingsLocked();
1804 }
1805 }
1806 return added;
1807 }
1808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 public boolean addPermission(PermissionInfo info) {
1810 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001811 return addPermissionLocked(info, false);
1812 }
1813 }
1814
1815 public boolean addPermissionAsync(PermissionInfo info) {
1816 synchronized (mPackages) {
1817 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 }
1819 }
1820
1821 public void removePermission(String name) {
1822 synchronized (mPackages) {
1823 checkPermissionTreeLP(name);
1824 BasePermission bp = mSettings.mPermissions.get(name);
1825 if (bp != null) {
1826 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1827 throw new SecurityException(
1828 "Not allowed to modify non-dynamic permission "
1829 + name);
1830 }
1831 mSettings.mPermissions.remove(name);
1832 mSettings.writeLP();
1833 }
1834 }
1835 }
1836
Dianne Hackborn854060af2009-07-09 18:14:31 -07001837 public boolean isProtectedBroadcast(String actionName) {
1838 synchronized (mPackages) {
1839 return mProtectedBroadcasts.contains(actionName);
1840 }
1841 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001843 public int checkSignatures(String pkg1, String pkg2) {
1844 synchronized (mPackages) {
1845 PackageParser.Package p1 = mPackages.get(pkg1);
1846 PackageParser.Package p2 = mPackages.get(pkg2);
1847 if (p1 == null || p1.mExtras == null
1848 || p2 == null || p2.mExtras == null) {
1849 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1850 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001851 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 }
1853 }
1854
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001855 public int checkUidSignatures(int uid1, int uid2) {
1856 synchronized (mPackages) {
1857 Signature[] s1;
1858 Signature[] s2;
1859 Object obj = mSettings.getUserIdLP(uid1);
1860 if (obj != null) {
1861 if (obj instanceof SharedUserSetting) {
1862 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1863 } else if (obj instanceof PackageSetting) {
1864 s1 = ((PackageSetting)obj).signatures.mSignatures;
1865 } else {
1866 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1867 }
1868 } else {
1869 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1870 }
1871 obj = mSettings.getUserIdLP(uid2);
1872 if (obj != null) {
1873 if (obj instanceof SharedUserSetting) {
1874 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1875 } else if (obj instanceof PackageSetting) {
1876 s2 = ((PackageSetting)obj).signatures.mSignatures;
1877 } else {
1878 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1879 }
1880 } else {
1881 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1882 }
1883 return checkSignaturesLP(s1, s2);
1884 }
1885 }
1886
1887 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1888 if (s1 == null) {
1889 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1891 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1892 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001893 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1895 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001896 HashSet<Signature> set1 = new HashSet<Signature>();
1897 for (Signature sig : s1) {
1898 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001900 HashSet<Signature> set2 = new HashSet<Signature>();
1901 for (Signature sig : s2) {
1902 set2.add(sig);
1903 }
1904 // Make sure s2 contains all signatures in s1.
1905 if (set1.equals(set2)) {
1906 return PackageManager.SIGNATURE_MATCH;
1907 }
1908 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 }
1910
1911 public String[] getPackagesForUid(int uid) {
1912 synchronized (mPackages) {
1913 Object obj = mSettings.getUserIdLP(uid);
1914 if (obj instanceof SharedUserSetting) {
1915 SharedUserSetting sus = (SharedUserSetting)obj;
1916 final int N = sus.packages.size();
1917 String[] res = new String[N];
1918 Iterator<PackageSetting> it = sus.packages.iterator();
1919 int i=0;
1920 while (it.hasNext()) {
1921 res[i++] = it.next().name;
1922 }
1923 return res;
1924 } else if (obj instanceof PackageSetting) {
1925 PackageSetting ps = (PackageSetting)obj;
1926 return new String[] { ps.name };
1927 }
1928 }
1929 return null;
1930 }
1931
1932 public String getNameForUid(int uid) {
1933 synchronized (mPackages) {
1934 Object obj = mSettings.getUserIdLP(uid);
1935 if (obj instanceof SharedUserSetting) {
1936 SharedUserSetting sus = (SharedUserSetting)obj;
1937 return sus.name + ":" + sus.userId;
1938 } else if (obj instanceof PackageSetting) {
1939 PackageSetting ps = (PackageSetting)obj;
1940 return ps.name;
1941 }
1942 }
1943 return null;
1944 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 public int getUidForSharedUser(String sharedUserName) {
1947 if(sharedUserName == null) {
1948 return -1;
1949 }
1950 synchronized (mPackages) {
1951 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1952 if(suid == null) {
1953 return -1;
1954 }
1955 return suid.userId;
1956 }
1957 }
1958
1959 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1960 int flags) {
1961 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001962 return chooseBestActivity(intent, resolvedType, flags, query);
1963 }
1964
Mihai Predaeae850c2009-05-13 10:13:48 +02001965 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1966 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 if (query != null) {
1968 final int N = query.size();
1969 if (N == 1) {
1970 return query.get(0);
1971 } else if (N > 1) {
1972 // If there is more than one activity with the same priority,
1973 // then let the user decide between them.
1974 ResolveInfo r0 = query.get(0);
1975 ResolveInfo r1 = query.get(1);
1976 if (false) {
1977 System.out.println(r0.activityInfo.name +
1978 "=" + r0.priority + " vs " +
1979 r1.activityInfo.name +
1980 "=" + r1.priority);
1981 }
1982 // If the first activity has a higher priority, or a different
1983 // default, then it is always desireable to pick it.
1984 if (r0.priority != r1.priority
1985 || r0.preferredOrder != r1.preferredOrder
1986 || r0.isDefault != r1.isDefault) {
1987 return query.get(0);
1988 }
1989 // If we have saved a preference for a preferred activity for
1990 // this Intent, use that.
1991 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1992 flags, query, r0.priority);
1993 if (ri != null) {
1994 return ri;
1995 }
1996 return mResolveInfo;
1997 }
1998 }
1999 return null;
2000 }
2001
2002 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
2003 int flags, List<ResolveInfo> query, int priority) {
2004 synchronized (mPackages) {
2005 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
2006 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02002007 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
2009 if (prefs != null && prefs.size() > 0) {
2010 // First figure out how good the original match set is.
2011 // We will only allow preferred activities that came
2012 // from the same match quality.
2013 int match = 0;
2014 final int N = query.size();
2015 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
2016 for (int j=0; j<N; j++) {
2017 ResolveInfo ri = query.get(j);
2018 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
2019 + ": 0x" + Integer.toHexString(match));
2020 if (ri.match > match) match = ri.match;
2021 }
2022 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
2023 + Integer.toHexString(match));
2024 match &= IntentFilter.MATCH_CATEGORY_MASK;
2025 final int M = prefs.size();
2026 for (int i=0; i<M; i++) {
2027 PreferredActivity pa = prefs.get(i);
2028 if (pa.mMatch != match) {
2029 continue;
2030 }
2031 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
2032 if (DEBUG_PREFERRED) {
2033 Log.v(TAG, "Got preferred activity:");
Marco Nelissend85621c2010-09-03 09:25:33 -07002034 if (ai != null) {
2035 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
2036 } else {
2037 Log.v(TAG, " null");
2038 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 }
2040 if (ai != null) {
2041 for (int j=0; j<N; j++) {
2042 ResolveInfo ri = query.get(j);
2043 if (!ri.activityInfo.applicationInfo.packageName
2044 .equals(ai.applicationInfo.packageName)) {
2045 continue;
2046 }
2047 if (!ri.activityInfo.name.equals(ai.name)) {
2048 continue;
2049 }
2050
2051 // Okay we found a previously set preferred app.
2052 // If the result set is different from when this
2053 // was created, we need to clear it and re-ask the
2054 // user their preference.
2055 if (!pa.sameSet(query, priority)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002056 Slog.i(TAG, "Result set changed, dropping preferred activity for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 + intent + " type " + resolvedType);
2058 mSettings.mPreferredActivities.removeFilter(pa);
2059 return null;
2060 }
2061
2062 // Yay!
2063 return ri;
2064 }
2065 }
2066 }
2067 }
2068 }
2069 return null;
2070 }
2071
2072 public List<ResolveInfo> queryIntentActivities(Intent intent,
2073 String resolvedType, int flags) {
2074 ComponentName comp = intent.getComponent();
2075 if (comp != null) {
2076 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2077 ActivityInfo ai = getActivityInfo(comp, flags);
2078 if (ai != null) {
2079 ResolveInfo ri = new ResolveInfo();
2080 ri.activityInfo = ai;
2081 list.add(ri);
2082 }
2083 return list;
2084 }
2085
2086 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002087 String pkgName = intent.getPackage();
2088 if (pkgName == null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002089 return (List<ResolveInfo>)mActivities.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002090 resolvedType, flags);
2091 }
2092 PackageParser.Package pkg = mPackages.get(pkgName);
2093 if (pkg != null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002094 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002095 resolvedType, flags, pkg.activities);
2096 }
Dianne Hackborn5d9d03a02011-01-24 13:15:09 -08002097 return new ArrayList<ResolveInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 }
2099 }
2100
2101 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2102 Intent[] specifics, String[] specificTypes, Intent intent,
2103 String resolvedType, int flags) {
2104 final String resultsAction = intent.getAction();
2105
2106 List<ResolveInfo> results = queryIntentActivities(
2107 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
2108 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
2109
2110 int specificsPos = 0;
2111 int N;
2112
2113 // todo: note that the algorithm used here is O(N^2). This
2114 // isn't a problem in our current environment, but if we start running
2115 // into situations where we have more than 5 or 10 matches then this
2116 // should probably be changed to something smarter...
2117
2118 // First we go through and resolve each of the specific items
2119 // that were supplied, taking care of removing any corresponding
2120 // duplicate items in the generic resolve list.
2121 if (specifics != null) {
2122 for (int i=0; i<specifics.length; i++) {
2123 final Intent sintent = specifics[i];
2124 if (sintent == null) {
2125 continue;
2126 }
2127
2128 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
2129 String action = sintent.getAction();
2130 if (resultsAction != null && resultsAction.equals(action)) {
2131 // If this action was explicitly requested, then don't
2132 // remove things that have it.
2133 action = null;
2134 }
2135 ComponentName comp = sintent.getComponent();
2136 ResolveInfo ri = null;
2137 ActivityInfo ai = null;
2138 if (comp == null) {
2139 ri = resolveIntent(
2140 sintent,
2141 specificTypes != null ? specificTypes[i] : null,
2142 flags);
2143 if (ri == null) {
2144 continue;
2145 }
2146 if (ri == mResolveInfo) {
2147 // ACK! Must do something better with this.
2148 }
2149 ai = ri.activityInfo;
2150 comp = new ComponentName(ai.applicationInfo.packageName,
2151 ai.name);
2152 } else {
2153 ai = getActivityInfo(comp, flags);
2154 if (ai == null) {
2155 continue;
2156 }
2157 }
2158
2159 // Look for any generic query activities that are duplicates
2160 // of this specific one, and remove them from the results.
2161 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
2162 N = results.size();
2163 int j;
2164 for (j=specificsPos; j<N; j++) {
2165 ResolveInfo sri = results.get(j);
2166 if ((sri.activityInfo.name.equals(comp.getClassName())
2167 && sri.activityInfo.applicationInfo.packageName.equals(
2168 comp.getPackageName()))
2169 || (action != null && sri.filter.matchAction(action))) {
2170 results.remove(j);
2171 if (Config.LOGV) Log.v(
2172 TAG, "Removing duplicate item from " + j
2173 + " due to specific " + specificsPos);
2174 if (ri == null) {
2175 ri = sri;
2176 }
2177 j--;
2178 N--;
2179 }
2180 }
2181
2182 // Add this specific item to its proper place.
2183 if (ri == null) {
2184 ri = new ResolveInfo();
2185 ri.activityInfo = ai;
2186 }
2187 results.add(specificsPos, ri);
2188 ri.specificIndex = i;
2189 specificsPos++;
2190 }
2191 }
2192
2193 // Now we go through the remaining generic results and remove any
2194 // duplicate actions that are found here.
2195 N = results.size();
2196 for (int i=specificsPos; i<N-1; i++) {
2197 final ResolveInfo rii = results.get(i);
2198 if (rii.filter == null) {
2199 continue;
2200 }
2201
2202 // Iterate over all of the actions of this result's intent
2203 // filter... typically this should be just one.
2204 final Iterator<String> it = rii.filter.actionsIterator();
2205 if (it == null) {
2206 continue;
2207 }
2208 while (it.hasNext()) {
2209 final String action = it.next();
2210 if (resultsAction != null && resultsAction.equals(action)) {
2211 // If this action was explicitly requested, then don't
2212 // remove things that have it.
2213 continue;
2214 }
2215 for (int j=i+1; j<N; j++) {
2216 final ResolveInfo rij = results.get(j);
2217 if (rij.filter != null && rij.filter.hasAction(action)) {
2218 results.remove(j);
2219 if (Config.LOGV) Log.v(
2220 TAG, "Removing duplicate item from " + j
2221 + " due to action " + action + " at " + i);
2222 j--;
2223 N--;
2224 }
2225 }
2226 }
2227
2228 // If the caller didn't request filter information, drop it now
2229 // so we don't have to marshall/unmarshall it.
2230 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2231 rii.filter = null;
2232 }
2233 }
2234
2235 // Filter out the caller activity if so requested.
2236 if (caller != null) {
2237 N = results.size();
2238 for (int i=0; i<N; i++) {
2239 ActivityInfo ainfo = results.get(i).activityInfo;
2240 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2241 && caller.getClassName().equals(ainfo.name)) {
2242 results.remove(i);
2243 break;
2244 }
2245 }
2246 }
2247
2248 // If the caller didn't request filter information,
2249 // drop them now so we don't have to
2250 // marshall/unmarshall it.
2251 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2252 N = results.size();
2253 for (int i=0; i<N; i++) {
2254 results.get(i).filter = null;
2255 }
2256 }
2257
2258 if (Config.LOGV) Log.v(TAG, "Result: " + results);
2259 return results;
2260 }
2261
2262 public List<ResolveInfo> queryIntentReceivers(Intent intent,
2263 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002264 ComponentName comp = intent.getComponent();
2265 if (comp != null) {
2266 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2267 ActivityInfo ai = getReceiverInfo(comp, flags);
2268 if (ai != null) {
2269 ResolveInfo ri = new ResolveInfo();
2270 ri.activityInfo = ai;
2271 list.add(ri);
2272 }
2273 return list;
2274 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002277 String pkgName = intent.getPackage();
2278 if (pkgName == null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002279 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002280 resolvedType, flags);
2281 }
2282 PackageParser.Package pkg = mPackages.get(pkgName);
2283 if (pkg != null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002284 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002285 resolvedType, flags, pkg.receivers);
2286 }
2287 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002288 }
2289 }
2290
2291 public ResolveInfo resolveService(Intent intent, String resolvedType,
2292 int flags) {
2293 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
2294 flags);
2295 if (query != null) {
2296 if (query.size() >= 1) {
2297 // If there is more than one service with the same priority,
2298 // just arbitrarily pick the first one.
2299 return query.get(0);
2300 }
2301 }
2302 return null;
2303 }
2304
2305 public List<ResolveInfo> queryIntentServices(Intent intent,
2306 String resolvedType, int flags) {
2307 ComponentName comp = intent.getComponent();
2308 if (comp != null) {
2309 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2310 ServiceInfo si = getServiceInfo(comp, flags);
2311 if (si != null) {
2312 ResolveInfo ri = new ResolveInfo();
2313 ri.serviceInfo = si;
2314 list.add(ri);
2315 }
2316 return list;
2317 }
2318
2319 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002320 String pkgName = intent.getPackage();
2321 if (pkgName == null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002322 return (List<ResolveInfo>)mServices.queryIntent(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002323 resolvedType, flags);
2324 }
2325 PackageParser.Package pkg = mPackages.get(pkgName);
2326 if (pkg != null) {
Jason parksa3cdaa52011-01-13 14:15:43 -06002327 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002328 resolvedType, flags, pkg.services);
2329 }
2330 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 }
2332 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 public List<PackageInfo> getInstalledPackages(int flags) {
2335 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2336
2337 synchronized (mPackages) {
2338 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2339 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2340 while (i.hasNext()) {
2341 final PackageSetting ps = i.next();
2342 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2343 if(psPkg != null) {
2344 finalList.add(psPkg);
2345 }
2346 }
2347 }
2348 else {
2349 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2350 while (i.hasNext()) {
2351 final PackageParser.Package p = i.next();
2352 if (p.applicationInfo != null) {
2353 PackageInfo pi = generatePackageInfo(p, flags);
2354 if(pi != null) {
2355 finalList.add(pi);
2356 }
2357 }
2358 }
2359 }
2360 }
2361 return finalList;
2362 }
2363
2364 public List<ApplicationInfo> getInstalledApplications(int flags) {
2365 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2366 synchronized(mPackages) {
2367 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2368 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2369 while (i.hasNext()) {
2370 final PackageSetting ps = i.next();
2371 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2372 if(ai != null) {
2373 finalList.add(ai);
2374 }
2375 }
2376 }
2377 else {
2378 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2379 while (i.hasNext()) {
2380 final PackageParser.Package p = i.next();
2381 if (p.applicationInfo != null) {
2382 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2383 if(ai != null) {
2384 finalList.add(ai);
2385 }
2386 }
2387 }
2388 }
2389 }
2390 return finalList;
2391 }
2392
2393 public List<ApplicationInfo> getPersistentApplications(int flags) {
2394 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2395
2396 synchronized (mPackages) {
2397 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2398 while (i.hasNext()) {
2399 PackageParser.Package p = i.next();
2400 if (p.applicationInfo != null
2401 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
Kenny Root85387d72010-08-26 10:13:11 -07002402 && (!mSafeMode || isSystemApp(p))) {
Jey2eebf5c2009-11-18 18:37:31 -08002403 finalList.add(PackageParser.generateApplicationInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 }
2405 }
2406 }
2407
2408 return finalList;
2409 }
2410
2411 public ProviderInfo resolveContentProvider(String name, int flags) {
2412 synchronized (mPackages) {
2413 final PackageParser.Provider provider = mProviders.get(name);
2414 return provider != null
2415 && mSettings.isEnabledLP(provider.info, flags)
2416 && (!mSafeMode || (provider.info.applicationInfo.flags
2417 &ApplicationInfo.FLAG_SYSTEM) != 0)
2418 ? PackageParser.generateProviderInfo(provider, flags)
2419 : null;
2420 }
2421 }
2422
Fred Quintana718d8a22009-04-29 17:53:20 -07002423 /**
2424 * @deprecated
2425 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 public void querySyncProviders(List outNames, List outInfo) {
2427 synchronized (mPackages) {
2428 Iterator<Map.Entry<String, PackageParser.Provider>> i
2429 = mProviders.entrySet().iterator();
2430
2431 while (i.hasNext()) {
2432 Map.Entry<String, PackageParser.Provider> entry = i.next();
2433 PackageParser.Provider p = entry.getValue();
2434
2435 if (p.syncable
2436 && (!mSafeMode || (p.info.applicationInfo.flags
2437 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2438 outNames.add(entry.getKey());
2439 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2440 }
2441 }
2442 }
2443 }
2444
2445 public List<ProviderInfo> queryContentProviders(String processName,
2446 int uid, int flags) {
2447 ArrayList<ProviderInfo> finalList = null;
2448
2449 synchronized (mPackages) {
2450 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2451 while (i.hasNext()) {
2452 PackageParser.Provider p = i.next();
2453 if (p.info.authority != null
2454 && (processName == null ||
2455 (p.info.processName.equals(processName)
2456 && p.info.applicationInfo.uid == uid))
2457 && mSettings.isEnabledLP(p.info, flags)
2458 && (!mSafeMode || (p.info.applicationInfo.flags
2459 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2460 if (finalList == null) {
2461 finalList = new ArrayList<ProviderInfo>(3);
2462 }
2463 finalList.add(PackageParser.generateProviderInfo(p,
2464 flags));
2465 }
2466 }
2467 }
2468
2469 if (finalList != null) {
2470 Collections.sort(finalList, mProviderInitOrderSorter);
2471 }
2472
2473 return finalList;
2474 }
2475
2476 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2477 int flags) {
2478 synchronized (mPackages) {
2479 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2480 return PackageParser.generateInstrumentationInfo(i, flags);
2481 }
2482 }
2483
2484 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2485 int flags) {
2486 ArrayList<InstrumentationInfo> finalList =
2487 new ArrayList<InstrumentationInfo>();
2488
2489 synchronized (mPackages) {
2490 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2491 while (i.hasNext()) {
2492 PackageParser.Instrumentation p = i.next();
2493 if (targetPackage == null
2494 || targetPackage.equals(p.info.targetPackage)) {
2495 finalList.add(PackageParser.generateInstrumentationInfo(p,
2496 flags));
2497 }
2498 }
2499 }
2500
2501 return finalList;
2502 }
2503
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002504 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 String[] files = dir.list();
Dianne Hackborn3b4bac72010-09-20 11:37:52 -07002506 if (files == null) {
2507 Log.d(TAG, "No files in app dir " + dir);
2508 return;
2509 }
2510
Joe Onorato431bb222010-10-18 19:13:23 -04002511 if (false) {
2512 Log.d(TAG, "Scanning app dir " + dir);
2513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514
2515 int i;
2516 for (i=0; i<files.length; i++) {
2517 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002518 if (!isPackageFilename(files[i])) {
2519 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002520 continue;
2521 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002522 PackageParser.Package pkg = scanPackageLI(file,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002523 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002524 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002525 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2526 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002527 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002528 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002529 file.delete();
2530 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 }
2532 }
2533
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002534 private static File getSettingsProblemFile() {
2535 File dataDir = Environment.getDataDirectory();
2536 File systemDir = new File(dataDir, "system");
2537 File fname = new File(systemDir, "uiderrors.txt");
2538 return fname;
2539 }
2540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002541 private static void reportSettingsProblem(int priority, String msg) {
2542 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002543 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002544 FileOutputStream out = new FileOutputStream(fname, true);
2545 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002546 SimpleDateFormat formatter = new SimpleDateFormat();
2547 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2548 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 pw.close();
2550 FileUtils.setPermissions(
2551 fname.toString(),
2552 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2553 -1, -1);
2554 } catch (java.io.IOException e) {
2555 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002556 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
2559 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2560 PackageParser.Package pkg, File srcFile, int parseFlags) {
2561 if (GET_CERTIFICATES) {
Jeff Browne7600722010-04-07 18:28:23 -07002562 if (ps != null
2563 && ps.codePath.equals(srcFile)
Kenny Root7d794fb2010-09-13 16:29:49 -07002564 && ps.timeStamp == srcFile.lastModified()) {
Jeff Browne7600722010-04-07 18:28:23 -07002565 if (ps.signatures.mSignatures != null
2566 && ps.signatures.mSignatures.length != 0) {
2567 // Optimization: reuse the existing cached certificates
2568 // if the package appears to be unchanged.
2569 pkg.mSignatures = ps.signatures.mSignatures;
2570 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 }
Jeff Browne7600722010-04-07 18:28:23 -07002572
2573 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002574 } else {
Jeff Browne7600722010-04-07 18:28:23 -07002575 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2576 }
2577
2578 if (!pp.collectCertificates(pkg, parseFlags)) {
2579 mLastScanError = pp.getParseError();
2580 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002581 }
2582 }
2583 return true;
2584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 /*
2587 * Scan a package and return the newly parsed package.
2588 * Returns null in case of errors and the error code is stored in mLastScanError
2589 */
2590 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002591 int parseFlags, int scanMode, long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002592 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002593 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002595 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002598 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002599 if (pkg == null) {
2600 mLastScanError = pp.getParseError();
2601 return null;
2602 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002603 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 PackageSetting updatedPkg;
2605 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002606 // Look to see if we already know about this package.
2607 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002608 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002609 // This package has been renamed to its original name. Let's
2610 // use that.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002611 ps = mSettings.peekPackageLP(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002612 }
2613 // If there was no original package, see one for the real package name.
2614 if (ps == null) {
2615 ps = mSettings.peekPackageLP(pkg.packageName);
2616 }
2617 // Check to see if this package could be hiding/updating a system
2618 // package. Must look for it either under the original or real
2619 // package name depending on our state.
2620 updatedPkg = mSettings.mDisabledSysPackages.get(
2621 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002623 // First check if this is a system package that may involve an update
2624 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
Kenny Root9ee92742010-09-01 13:40:57 -07002625 if (ps != null && !ps.codePath.equals(scanFile)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002626 // The path has changed from what was last scanned... check the
2627 // version of the new path against what we have stored to determine
2628 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002629 if (pkg.mVersionCode < ps.versionCode) {
2630 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002631 // Ignore entry. Skip it.
2632 Log.i(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborncef65ee2010-09-30 18:27:22 -07002633 + " ignored: updated version " + ps.versionCode
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002634 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002635 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2636 return null;
2637 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002638 // The current app on the system partion is better than
2639 // what we have updated to on the data partition; switch
2640 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002641 // At this point, its safely assumed that package installation for
2642 // apps in system partition will go through. If not there won't be a working
2643 // version of the app
2644 synchronized (mPackages) {
2645 // Just remove the loaded entries from package lists.
2646 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002647 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002648 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002649 + "reverting from " + ps.codePathString
2650 + ": new version " + pkg.mVersionCode
2651 + " better than installed " + ps.versionCode);
Kenny Root85387d72010-08-26 10:13:11 -07002652 InstallArgs args = new FileInstallArgs(ps.codePathString,
2653 ps.resourcePathString, ps.nativeLibraryPathString);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002654 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002655 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 }
2658 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002659 if (updatedPkg != null) {
2660 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2661 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2662 }
2663 // Verify certificates against what was last scanned
2664 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002665 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002666 return null;
2667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 // The apk is forward locked (not public) if its code and resources
2669 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002670 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002672 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002673 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002674
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002675 String codePath = null;
2676 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002677 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2678 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002679 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002680 } else {
2681 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002682 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002683 }
2684 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002685 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002686 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002687 codePath = pkg.mScanPath;
2688 // Set application objects path explicitly.
2689 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 // Note that we invoke the following method only if we are about to unpack an application
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002691 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002692 }
2693
Kenny Root85387d72010-08-26 10:13:11 -07002694 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
2695 String destResPath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002696 pkg.mPath = pkg.mScanPath = destCodePath;
2697 pkg.applicationInfo.sourceDir = destCodePath;
2698 pkg.applicationInfo.publicSourceDir = destResPath;
2699 }
2700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 private static String fixProcessName(String defProcessName,
2702 String processName, int uid) {
2703 if (processName == null) {
2704 return defProcessName;
2705 }
2706 return processName;
2707 }
2708
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002709 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002710 PackageParser.Package pkg) {
2711 if (pkgSetting.signatures.mSignatures != null) {
2712 // Already existing package. Make sure signatures match
2713 if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
2714 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002715 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002716 + " signatures do not match the previously installed version; ignoring!");
2717 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002718 return false;
2719 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002720 }
2721 // Check for shared user signatures
2722 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
2723 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
2724 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
2725 Slog.e(TAG, "Package " + pkg.packageName
2726 + " has no signatures that match those in shared user "
2727 + pkgSetting.sharedUser.name + "; ignoring!");
2728 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2729 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
2732 return true;
2733 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002734
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002735 public boolean performDexOpt(String packageName) {
2736 if (!mNoDexOpt) {
2737 return false;
2738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002739
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002740 PackageParser.Package p;
2741 synchronized (mPackages) {
2742 p = mPackages.get(packageName);
2743 if (p == null || p.mDidDexOpt) {
2744 return false;
2745 }
2746 }
2747 synchronized (mInstallLock) {
2748 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2749 }
2750 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002751
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002752 static final int DEX_OPT_SKIPPED = 0;
2753 static final int DEX_OPT_PERFORMED = 1;
2754 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002755
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002756 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2757 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002758 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002759 String path = pkg.mScanPath;
2760 int ret = 0;
2761 try {
2762 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002763 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002764 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002765 pkg.mDidDexOpt = true;
2766 performed = true;
2767 }
2768 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002769 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002770 ret = -1;
2771 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07002772 Slog.w(TAG, "IOException reading apk: " + path, e);
2773 ret = -1;
2774 } catch (dalvik.system.StaleDexCacheError e) {
2775 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
2776 ret = -1;
2777 } catch (Exception e) {
2778 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002779 ret = -1;
2780 }
2781 if (ret < 0) {
2782 //error from installer
2783 return DEX_OPT_FAILED;
2784 }
2785 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002786
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002787 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2788 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002789
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002790 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2791 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002792 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002793 + " to " + newPkg.packageName
2794 + ": old package not in system partition");
2795 return false;
2796 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002797 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002798 + " to " + newPkg.packageName
2799 + ": old package still exists");
2800 return false;
2801 }
2802 return true;
2803 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002804
2805 private File getDataPathForPackage(PackageParser.Package pkg) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08002806 final File dataPath = new File(mAppDataDir, pkg.packageName);
Jason parksa3cdaa52011-01-13 14:15:43 -06002807 return dataPath;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002808 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002809
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002810 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07002811 int parseFlags, int scanMode, long currentTime) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002812 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002813 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2814 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002815 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002816 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002817 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2818 return null;
2819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 mScanningPath = scanFile;
2821 if (pkg == null) {
2822 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2823 return null;
2824 }
2825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2827 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2828 }
2829
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002830 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 synchronized (mPackages) {
2832 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002833 Slog.w(TAG, "*************************************************");
2834 Slog.w(TAG, "Core android package being redefined. Skipping.");
2835 Slog.w(TAG, " file=" + mScanningPath);
2836 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2838 return null;
2839 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 // Set up information for our fall-back user intent resolution
2842 // activity.
2843 mPlatformPackage = pkg;
2844 pkg.mVersionCode = mSdkVersion;
2845 mAndroidApplication = pkg.applicationInfo;
2846 mResolveActivity.applicationInfo = mAndroidApplication;
2847 mResolveActivity.name = ResolverActivity.class.getName();
2848 mResolveActivity.packageName = mAndroidApplication.packageName;
2849 mResolveActivity.processName = mAndroidApplication.processName;
2850 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2851 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
Joe Onorato646f46e2010-11-08 15:08:56 -08002852 mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002853 mResolveActivity.exported = true;
2854 mResolveActivity.enabled = true;
2855 mResolveInfo.activityInfo = mResolveActivity;
2856 mResolveInfo.priority = 0;
2857 mResolveInfo.preferredOrder = 0;
2858 mResolveInfo.match = 0;
2859 mResolveComponentName = new ComponentName(
2860 mAndroidApplication.packageName, mResolveActivity.name);
2861 }
2862 }
2863
2864 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002865 TAG, "Scanning package " + pkg.packageName);
2866 if (mPackages.containsKey(pkg.packageName)
2867 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002868 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 + " already installed. Skipping duplicate.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2871 return null;
2872 }
2873
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002874 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002875 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2876 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002878 SharedUserSetting suid = null;
2879 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002880
Kenny Root502e9a42011-01-10 13:48:15 -08002881 if (!isSystemApp(pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002882 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002883 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002884 pkg.mRealPackage = null;
2885 pkg.mAdoptPermissions = null;
2886 }
Kenny Root502e9a42011-01-10 13:48:15 -08002887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 synchronized (mPackages) {
2889 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002890 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2891 if (mTmpSharedLibraries == null ||
2892 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2893 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2894 }
2895 int num = 0;
2896 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2897 for (int i=0; i<N; i++) {
2898 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002900 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002902 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2904 return null;
2905 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002906 mTmpSharedLibraries[num] = file;
2907 num++;
2908 }
2909 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2910 for (int i=0; i<N; i++) {
2911 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2912 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002913 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07002914 + " desires unavailable shared library "
2915 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2916 } else {
2917 mTmpSharedLibraries[num] = file;
2918 num++;
2919 }
2920 }
2921 if (num > 0) {
2922 pkg.usesLibraryFiles = new String[num];
2923 System.arraycopy(mTmpSharedLibraries, 0,
2924 pkg.usesLibraryFiles, 0, num);
2925 }
Kenny Root1683afa2011-01-07 14:27:50 -08002926 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 if (pkg.mSharedUserId != null) {
2929 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2930 pkg.applicationInfo.flags, true);
2931 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002932 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 + " for shared user failed");
2934 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2935 return null;
2936 }
2937 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2938 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2939 + suid.userId + "): packages=" + suid.packages);
2940 }
2941 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002942
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002943 if (false) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002944 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002945 Log.w(TAG, "WAITING FOR DEBUGGER");
2946 Debug.waitForDebugger();
Dianne Hackbornc1552392010-03-03 16:19:01 -08002947 Log.i(TAG, "Package " + pkg.packageName + " from original packages"
2948 + pkg.mOriginalPackages);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002949 }
2950 }
2951
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002952 // Check if we are renaming from an original package name.
2953 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002954 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08002955 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002956 // This package may need to be renamed to a previously
2957 // installed name. Let's check on that...
2958 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002959 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002960 // This package had originally been installed as the
2961 // original name, and we have already taken care of
2962 // transitioning to the new one. Just update the new
2963 // one to continue using the old name.
2964 realName = pkg.mRealPackage;
2965 if (!pkg.packageName.equals(renamed)) {
2966 // Callers into this function may have already taken
2967 // care of renaming the package; only do it here if
2968 // it is not already done.
2969 pkg.setPackageName(renamed);
2970 }
2971
Dianne Hackbornc1552392010-03-03 16:19:01 -08002972 } else {
2973 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
2974 if ((origPackage=mSettings.peekPackageLP(
2975 pkg.mOriginalPackages.get(i))) != null) {
2976 // We do have the package already installed under its
2977 // original name... should we use it?
2978 if (!verifyPackageUpdate(origPackage, pkg)) {
2979 // New package is not compatible with original.
2980 origPackage = null;
2981 continue;
2982 } else if (origPackage.sharedUser != null) {
2983 // Make sure uid is compatible between packages.
2984 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002985 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08002986 + " to " + pkg.packageName + ": old uid "
2987 + origPackage.sharedUser.name
2988 + " differs from " + pkg.mSharedUserId);
2989 origPackage = null;
2990 continue;
2991 }
2992 } else {
2993 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
2994 + pkg.packageName + " to old name " + origPackage.name);
2995 }
2996 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002997 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002998 }
2999 }
3000 }
3001
3002 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003003 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003004 + " was transferred to another, but its .apk remains");
3005 }
3006
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003007 // Just create the setting, don't add it yet. For already existing packages
3008 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003009 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
Kenny Root806cc132010-09-12 08:34:19 -07003010 destResourceFile, pkg.applicationInfo.nativeLibraryDir,
3011 pkg.applicationInfo.flags, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003013 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3015 return null;
3016 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003017
3018 if (pkgSetting.origPackage != null) {
3019 // If we are first transitioning from an original package,
3020 // fix up the new package's name now. We need to do this after
3021 // looking up the package under its new name, so getPackageLP
3022 // can take care of fiddling things correctly.
3023 pkg.setPackageName(origPackage.name);
3024
3025 // File a report about this.
3026 String msg = "New package " + pkgSetting.realName
3027 + " renamed to replace old package " + pkgSetting.name;
3028 reportSettingsProblem(Log.WARN, msg);
3029
3030 // Make a note of it.
3031 mTransferedPackages.add(origPackage.name);
3032
3033 // No longer need to retain this.
3034 pkgSetting.origPackage = null;
3035 }
3036
3037 if (realName != null) {
3038 // Make a note of it.
3039 mTransferedPackages.add(pkg.packageName);
3040 }
3041
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003042 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003043 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
3044 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 pkg.applicationInfo.uid = pkgSetting.userId;
3047 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003048
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003049 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003050 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 return null;
3052 }
3053 // The signature has changed, but this package is in the system
3054 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07003055 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 // However... if this package is part of a shared user, but it
3057 // doesn't match the signature of the shared user, let's fail.
3058 // What this means is that you can't change the signatures
3059 // associated with an overall shared user, which doesn't seem all
3060 // that unreasonable.
3061 if (pkgSetting.sharedUser != null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07003062 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
3063 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
3064 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3066 return null;
3067 }
3068 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003069 // File a report about this.
3070 String msg = "System package " + pkg.packageName
3071 + " signature changed; retaining data.";
3072 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003074
The Android Open Source Project10592532009-03-18 17:39:46 -07003075 // Verify that this new package doesn't have any content providers
3076 // that conflict with existing packages. Only do this if the
3077 // package isn't already installed, since we don't want to break
3078 // things that are installed.
3079 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
3080 int N = pkg.providers.size();
3081 int i;
3082 for (i=0; i<N; i++) {
3083 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003084 if (p.info.authority != null) {
3085 String names[] = p.info.authority.split(";");
3086 for (int j = 0; j < names.length; j++) {
3087 if (mProviders.containsKey(names[j])) {
3088 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003089 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003090 " (in package " + pkg.applicationInfo.packageName +
3091 ") is already used by "
3092 + ((other != null && other.getComponentName() != null)
3093 ? other.getComponentName().getPackageName() : "?"));
3094 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3095 return null;
3096 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003097 }
3098 }
3099 }
3100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 }
3102
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003103 final String pkgName = pkg.packageName;
3104
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003105 if (pkg.mAdoptPermissions != null) {
3106 // This package wants to adopt ownership of permissions from
3107 // another package.
3108 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
3109 String origName = pkg.mAdoptPermissions.get(i);
3110 PackageSetting orig = mSettings.peekPackageLP(origName);
3111 if (orig != null) {
3112 if (verifyPackageUpdate(orig, pkg)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003113 Slog.i(TAG, "Adopting permissions from "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003114 + origName + " to " + pkg.packageName);
3115 mSettings.transferPermissions(origName, pkg.packageName);
3116 }
3117 }
3118 }
3119 }
3120
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003121 final long scanFileTime = scanFile.lastModified();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
Kenny Root7d794fb2010-09-13 16:29:49 -07003123 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.timeStamp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 pkg.applicationInfo.processName = fixProcessName(
3125 pkg.applicationInfo.packageName,
3126 pkg.applicationInfo.processName,
3127 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128
3129 File dataPath;
3130 if (mPlatformPackage == pkg) {
3131 // The system package is special.
3132 dataPath = new File (Environment.getDataDirectory(), "system");
3133 pkg.applicationInfo.dataDir = dataPath.getPath();
3134 } else {
3135 // This is a normal package, need to make its data directory.
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003136 dataPath = getDataPathForPackage(pkg);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003137
3138 boolean uidError = false;
3139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 if (dataPath.exists()) {
3141 mOutPermissions[1] = 0;
3142 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
Kenny Root85387d72010-08-26 10:13:11 -07003143
3144 // If we have mismatched owners for the data path, we have a
3145 // problem (unless we're running in the simulator.)
3146 if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003147 boolean recovered = false;
3148 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3149 // If this is a system app, we can at least delete its
3150 // current data so the application will still work.
3151 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08003152 int ret = mInstaller.remove(pkgName);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003153 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003154 // Old data gone!
3155 String msg = "System package " + pkg.packageName
3156 + " has changed from uid: "
3157 + mOutPermissions[1] + " to "
3158 + pkg.applicationInfo.uid + "; old data erased";
3159 reportSettingsProblem(Log.WARN, msg);
3160 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 // And now re-install the app.
Kenny Root35ab3ad2011-02-02 16:42:14 -08003163 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003164 pkg.applicationInfo.uid);
3165 if (ret == -1) {
3166 // Ack should not happen!
3167 msg = "System package " + pkg.packageName
3168 + " could not have data directory re-created after delete.";
3169 reportSettingsProblem(Log.WARN, msg);
3170 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3171 return null;
3172 }
3173 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 if (!recovered) {
3176 mHasSystemUidErrors = true;
3177 }
3178 }
3179 if (!recovered) {
3180 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3181 + pkg.applicationInfo.uid + "/fs_"
3182 + mOutPermissions[1];
Kenny Root85387d72010-08-26 10:13:11 -07003183 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003184 String msg = "Package " + pkg.packageName
3185 + " has mismatched uid: "
3186 + mOutPermissions[1] + " on disk, "
3187 + pkg.applicationInfo.uid + " in settings";
3188 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003189 mSettings.mReadMessages.append(msg);
3190 mSettings.mReadMessages.append('\n');
3191 uidError = true;
3192 if (!pkgSetting.uidError) {
3193 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 }
3196 }
3197 }
3198 pkg.applicationInfo.dataDir = dataPath.getPath();
3199 } else {
3200 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
3201 Log.v(TAG, "Want this data dir: " + dataPath);
3202 //invoke installer to do the actual installation
3203 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08003204 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 pkg.applicationInfo.uid);
3206 if(ret < 0) {
3207 // Error from installer
3208 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3209 return null;
3210 }
3211 } else {
3212 dataPath.mkdirs();
3213 if (dataPath.exists()) {
3214 FileUtils.setPermissions(
3215 dataPath.toString(),
3216 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3217 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
3218 }
3219 }
3220 if (dataPath.exists()) {
3221 pkg.applicationInfo.dataDir = dataPath.getPath();
3222 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003223 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 pkg.applicationInfo.dataDir = null;
3225 }
3226 }
Kenny Root85387d72010-08-26 10:13:11 -07003227
3228 /*
3229 * Set the data dir to the default "/data/data/<package name>/lib"
3230 * if we got here without anyone telling us different (e.g., apps
3231 * stored on SD card have their native libraries stored in the ASEC
3232 * container with the APK).
Kenny Root806cc132010-09-12 08:34:19 -07003233 *
3234 * This happens during an upgrade from a package settings file that
3235 * doesn't have a native library path attribute at all.
Kenny Root85387d72010-08-26 10:13:11 -07003236 */
Kenny Rootbd135c12010-10-05 12:26:27 -07003237 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
3238 if (pkgSetting.nativeLibraryPathString == null) {
3239 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath();
3240 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
3241 pkgSetting.nativeLibraryPathString = nativeLibraryPath;
3242 } else {
3243 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
3244 }
Kenny Root85387d72010-08-26 10:13:11 -07003245 }
3246
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003247 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
3249
Kenny Root85387d72010-08-26 10:13:11 -07003250 // If we're running in the simulator, we don't need to unpack anything.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 if (mInstaller != null) {
3252 String path = scanFile.getPath();
Kenny Root85387d72010-08-26 10:13:11 -07003253 /* Note: We don't want to unpack the native binaries for
3254 * system applications, unless they have been updated
3255 * (the binaries are already under /system/lib).
3256 * Also, don't unpack libs for apps on the external card
3257 * since they should have their libraries in the ASEC
3258 * container already.
3259 *
3260 * In other words, we're going to unpack the binaries
3261 * only for non-system apps and system app upgrades.
3262 */
Kenny Root831baa22010-10-05 12:29:25 -07003263 if (pkg.applicationInfo.nativeLibraryDir != null) {
Kenny Roote68d58a2010-10-18 16:08:54 -07003264 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
3265 final String dataPathString = dataPath.getPath();
3266
Kenny Root831baa22010-10-05 12:29:25 -07003267 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
3268 /*
3269 * Upgrading from a previous version of the OS sometimes
3270 * leaves native libraries in the /data/data/<app>/lib
3271 * directory for system apps even when they shouldn't be.
3272 * Recent changes in the JNI library search path
3273 * necessitates we remove those to match previous behavior.
3274 */
Kenny Roote68d58a2010-10-18 16:08:54 -07003275 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
Kenny Root831baa22010-10-05 12:29:25 -07003276 Log.i(TAG, "removed obsolete native libraries for system package " + path);
3277 }
Kenny Roote68d58a2010-10-18 16:08:54 -07003278 } else if (nativeLibraryDir.getParent().equals(dataPathString)) {
3279 /*
3280 * If this is an internal application or our
3281 * nativeLibraryPath points to our data directory, unpack
3282 * the libraries. The native library path pointing to the
3283 * data directory for an application in an ASEC container
3284 * can happen for older apps that existed before an OTA to
3285 * Gingerbread.
3286 */
3287 Slog.i(TAG, "Unpacking native libraries for " + path);
3288 mInstaller.unlinkNativeLibraryDirectory(dataPathString);
3289 NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
Kenny Root6a6b0072010-10-07 16:46:10 -07003290 } else {
Kenny Roote68d58a2010-10-18 16:08:54 -07003291 Slog.i(TAG, "Linking native library dir for " + path);
3292 mInstaller.linkNativeLibraryDirectory(dataPathString,
Kenny Root6a6b0072010-10-07 16:46:10 -07003293 pkg.applicationInfo.nativeLibraryDir);
Kenny Root831baa22010-10-05 12:29:25 -07003294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003296 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003297
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003298 if ((scanMode&SCAN_NO_DEX) == 0) {
3299 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3301 return null;
3302 }
3303 }
3304 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003306 if (mFactoryTest && pkg.requestedPermissions.contains(
3307 android.Manifest.permission.FACTORY_TEST)) {
3308 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3309 }
3310
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003311 // Request the ActivityManager to kill the process(only for existing packages)
3312 // so that we do not end up in a confused state while the user is still using the older
3313 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003314 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003315 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003316 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003317 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003320 // We don't expect installation to fail beyond this point,
3321 if ((scanMode&SCAN_MONITOR) != 0) {
3322 mAppDirs.put(pkg.mPath, pkg);
3323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003324 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003325 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003327 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003328 // Make sure we don't accidentally delete its data.
3329 mSettings.mPackagesToBeCleaned.remove(pkgName);
3330
Dianne Hackborn78d6883692010-10-07 01:12:46 -07003331 // Take care of first install / last update times.
3332 if (currentTime != 0) {
3333 if (pkgSetting.firstInstallTime == 0) {
3334 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
3335 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
3336 pkgSetting.lastUpdateTime = currentTime;
3337 }
3338 } else if (pkgSetting.firstInstallTime == 0) {
3339 // We need *something*. Take time time stamp of the file.
3340 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
3341 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
3342 if (scanFileTime != pkgSetting.timeStamp) {
3343 // A package on the system image has changed; consider this
3344 // to be an update.
3345 pkgSetting.lastUpdateTime = scanFileTime;
3346 }
3347 }
3348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 int N = pkg.providers.size();
3350 StringBuilder r = null;
3351 int i;
3352 for (i=0; i<N; i++) {
3353 PackageParser.Provider p = pkg.providers.get(i);
3354 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3355 p.info.processName, pkg.applicationInfo.uid);
3356 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3357 p.info.name), p);
3358 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003359 if (p.info.authority != null) {
3360 String names[] = p.info.authority.split(";");
3361 p.info.authority = null;
3362 for (int j = 0; j < names.length; j++) {
3363 if (j == 1 && p.syncable) {
3364 // We only want the first authority for a provider to possibly be
3365 // syncable, so if we already added this provider using a different
3366 // authority clear the syncable flag. We copy the provider before
3367 // changing it because the mProviders object contains a reference
3368 // to a provider that we don't want to change.
3369 // Only do this for the second authority since the resulting provider
3370 // object can be the same for all future authorities for this provider.
3371 p = new PackageParser.Provider(p);
3372 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003374 if (!mProviders.containsKey(names[j])) {
3375 mProviders.put(names[j], p);
3376 if (p.info.authority == null) {
3377 p.info.authority = names[j];
3378 } else {
3379 p.info.authority = p.info.authority + ";" + names[j];
3380 }
3381 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
3382 Log.d(TAG, "Registered content provider: " + names[j] +
3383 ", className = " + p.info.name +
3384 ", isSyncable = " + p.info.isSyncable);
3385 } else {
3386 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003387 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003388 " (in package " + pkg.applicationInfo.packageName +
3389 "): name already used by "
3390 + ((other != null && other.getComponentName() != null)
3391 ? other.getComponentName().getPackageName() : "?"));
3392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 }
3394 }
3395 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3396 if (r == null) {
3397 r = new StringBuilder(256);
3398 } else {
3399 r.append(' ');
3400 }
3401 r.append(p.info.name);
3402 }
3403 }
3404 if (r != null) {
3405 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3406 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 N = pkg.services.size();
3409 r = null;
3410 for (i=0; i<N; i++) {
3411 PackageParser.Service s = pkg.services.get(i);
3412 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3413 s.info.processName, pkg.applicationInfo.uid);
3414 mServices.addService(s);
3415 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3416 if (r == null) {
3417 r = new StringBuilder(256);
3418 } else {
3419 r.append(' ');
3420 }
3421 r.append(s.info.name);
3422 }
3423 }
3424 if (r != null) {
3425 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 N = pkg.receivers.size();
3429 r = null;
3430 for (i=0; i<N; i++) {
3431 PackageParser.Activity a = pkg.receivers.get(i);
3432 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3433 a.info.processName, pkg.applicationInfo.uid);
3434 mReceivers.addActivity(a, "receiver");
3435 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3436 if (r == null) {
3437 r = new StringBuilder(256);
3438 } else {
3439 r.append(' ');
3440 }
3441 r.append(a.info.name);
3442 }
3443 }
3444 if (r != null) {
3445 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3446 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 N = pkg.activities.size();
3449 r = null;
3450 for (i=0; i<N; i++) {
3451 PackageParser.Activity a = pkg.activities.get(i);
3452 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3453 a.info.processName, pkg.applicationInfo.uid);
3454 mActivities.addActivity(a, "activity");
3455 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3456 if (r == null) {
3457 r = new StringBuilder(256);
3458 } else {
3459 r.append(' ');
3460 }
3461 r.append(a.info.name);
3462 }
3463 }
3464 if (r != null) {
3465 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 N = pkg.permissionGroups.size();
3469 r = null;
3470 for (i=0; i<N; i++) {
3471 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3472 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3473 if (cur == null) {
3474 mPermissionGroups.put(pg.info.name, pg);
3475 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3476 if (r == null) {
3477 r = new StringBuilder(256);
3478 } else {
3479 r.append(' ');
3480 }
3481 r.append(pg.info.name);
3482 }
3483 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003484 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 + pg.info.packageName + " ignored: original from "
3486 + cur.info.packageName);
3487 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3488 if (r == null) {
3489 r = new StringBuilder(256);
3490 } else {
3491 r.append(' ');
3492 }
3493 r.append("DUP:");
3494 r.append(pg.info.name);
3495 }
3496 }
3497 }
3498 if (r != null) {
3499 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 N = pkg.permissions.size();
3503 r = null;
3504 for (i=0; i<N; i++) {
3505 PackageParser.Permission p = pkg.permissions.get(i);
3506 HashMap<String, BasePermission> permissionMap =
3507 p.tree ? mSettings.mPermissionTrees
3508 : mSettings.mPermissions;
3509 p.group = mPermissionGroups.get(p.info.group);
3510 if (p.info.group == null || p.group != null) {
3511 BasePermission bp = permissionMap.get(p.info.name);
3512 if (bp == null) {
3513 bp = new BasePermission(p.info.name, p.info.packageName,
3514 BasePermission.TYPE_NORMAL);
3515 permissionMap.put(p.info.name, bp);
3516 }
3517 if (bp.perm == null) {
3518 if (bp.sourcePackage == null
3519 || bp.sourcePackage.equals(p.info.packageName)) {
3520 BasePermission tree = findPermissionTreeLP(p.info.name);
3521 if (tree == null
3522 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003523 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 bp.perm = p;
3525 bp.uid = pkg.applicationInfo.uid;
3526 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3527 if (r == null) {
3528 r = new StringBuilder(256);
3529 } else {
3530 r.append(' ');
3531 }
3532 r.append(p.info.name);
3533 }
3534 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003535 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 + p.info.packageName + " ignored: base tree "
3537 + tree.name + " is from package "
3538 + tree.sourcePackage);
3539 }
3540 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003541 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 + p.info.packageName + " ignored: original from "
3543 + bp.sourcePackage);
3544 }
3545 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3546 if (r == null) {
3547 r = new StringBuilder(256);
3548 } else {
3549 r.append(' ');
3550 }
3551 r.append("DUP:");
3552 r.append(p.info.name);
3553 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003554 if (bp.perm == p) {
3555 bp.protectionLevel = p.info.protectionLevel;
3556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003558 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 + p.info.packageName + " ignored: no group "
3560 + p.group);
3561 }
3562 }
3563 if (r != null) {
3564 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3565 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 N = pkg.instrumentation.size();
3568 r = null;
3569 for (i=0; i<N; i++) {
3570 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3571 a.info.packageName = pkg.applicationInfo.packageName;
3572 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3573 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3574 a.info.dataDir = pkg.applicationInfo.dataDir;
Kenny Root85387d72010-08-26 10:13:11 -07003575 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003576 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3578 if (r == null) {
3579 r = new StringBuilder(256);
3580 } else {
3581 r.append(' ');
3582 }
3583 r.append(a.info.name);
3584 }
3585 }
3586 if (r != null) {
3587 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003589
Dianne Hackborn854060af2009-07-09 18:14:31 -07003590 if (pkg.protectedBroadcasts != null) {
3591 N = pkg.protectedBroadcasts.size();
3592 for (i=0; i<N; i++) {
3593 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3594 }
3595 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 pkgSetting.setTimeStamp(scanFileTime);
3598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 return pkg;
3601 }
3602
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003603 private void killApplication(String pkgName, int uid) {
3604 // Request the ActivityManager to kill the process(only for existing packages)
3605 // so that we do not end up in a confused state while the user is still using the older
3606 // version of the application while the new one gets installed.
3607 IActivityManager am = ActivityManagerNative.getDefault();
3608 if (am != null) {
3609 try {
3610 am.killApplicationWithUid(pkgName, uid);
3611 } catch (RemoteException e) {
3612 }
3613 }
3614 }
3615
David 'Digit' Turner4f99e3c2010-04-12 16:11:15 -07003616 // Return the path of the directory that will contain the native binaries
3617 // of a given installed package. This is relative to the data path.
3618 //
Kenny Root85387d72010-08-26 10:13:11 -07003619 private File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
3620 final String nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
3621 if (nativeLibraryDir != null) {
3622 return new File(nativeLibraryDir);
3623 } else {
3624 // Fall back for old packages
3625 return new File(pkg.applicationInfo.dataDir, LIB_DIR_NAME);
3626 }
David 'Digit' Turner4f99e3c2010-04-12 16:11:15 -07003627 }
3628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003629 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3630 if (chatty && Config.LOGD) Log.d(
3631 TAG, "Removing package " + pkg.applicationInfo.packageName );
3632
3633 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 mPackages.remove(pkg.applicationInfo.packageName);
3637 if (pkg.mPath != null) {
3638 mAppDirs.remove(pkg.mPath);
3639 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 int N = pkg.providers.size();
3642 StringBuilder r = null;
3643 int i;
3644 for (i=0; i<N; i++) {
3645 PackageParser.Provider p = pkg.providers.get(i);
3646 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3647 p.info.name));
3648 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 /* The is another ContentProvider with this authority when
3651 * this app was installed so this authority is null,
3652 * Ignore it as we don't have to unregister the provider.
3653 */
3654 continue;
3655 }
3656 String names[] = p.info.authority.split(";");
3657 for (int j = 0; j < names.length; j++) {
3658 if (mProviders.get(names[j]) == p) {
3659 mProviders.remove(names[j]);
3660 if (chatty && Config.LOGD) Log.d(
3661 TAG, "Unregistered content provider: " + names[j] +
3662 ", className = " + p.info.name +
3663 ", isSyncable = " + p.info.isSyncable);
3664 }
3665 }
3666 if (chatty) {
3667 if (r == null) {
3668 r = new StringBuilder(256);
3669 } else {
3670 r.append(' ');
3671 }
3672 r.append(p.info.name);
3673 }
3674 }
3675 if (r != null) {
3676 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3677 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 N = pkg.services.size();
3680 r = null;
3681 for (i=0; i<N; i++) {
3682 PackageParser.Service s = pkg.services.get(i);
3683 mServices.removeService(s);
3684 if (chatty) {
3685 if (r == null) {
3686 r = new StringBuilder(256);
3687 } else {
3688 r.append(' ');
3689 }
3690 r.append(s.info.name);
3691 }
3692 }
3693 if (r != null) {
3694 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3695 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 N = pkg.receivers.size();
3698 r = null;
3699 for (i=0; i<N; i++) {
3700 PackageParser.Activity a = pkg.receivers.get(i);
3701 mReceivers.removeActivity(a, "receiver");
3702 if (chatty) {
3703 if (r == null) {
3704 r = new StringBuilder(256);
3705 } else {
3706 r.append(' ');
3707 }
3708 r.append(a.info.name);
3709 }
3710 }
3711 if (r != null) {
3712 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3713 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003715 N = pkg.activities.size();
3716 r = null;
3717 for (i=0; i<N; i++) {
3718 PackageParser.Activity a = pkg.activities.get(i);
3719 mActivities.removeActivity(a, "activity");
3720 if (chatty) {
3721 if (r == null) {
3722 r = new StringBuilder(256);
3723 } else {
3724 r.append(' ');
3725 }
3726 r.append(a.info.name);
3727 }
3728 }
3729 if (r != null) {
3730 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3731 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 N = pkg.permissions.size();
3734 r = null;
3735 for (i=0; i<N; i++) {
3736 PackageParser.Permission p = pkg.permissions.get(i);
3737 boolean tree = false;
3738 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3739 if (bp == null) {
3740 tree = true;
3741 bp = mSettings.mPermissionTrees.get(p.info.name);
3742 }
3743 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003744 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 if (chatty) {
3746 if (r == null) {
3747 r = new StringBuilder(256);
3748 } else {
3749 r.append(' ');
3750 }
3751 r.append(p.info.name);
3752 }
3753 }
3754 }
3755 if (r != null) {
3756 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3757 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 N = pkg.instrumentation.size();
3760 r = null;
3761 for (i=0; i<N; i++) {
3762 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003763 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 if (chatty) {
3765 if (r == null) {
3766 r = new StringBuilder(256);
3767 } else {
3768 r.append(' ');
3769 }
3770 r.append(a.info.name);
3771 }
3772 }
3773 if (r != null) {
3774 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3775 }
3776 }
3777 }
3778
3779 private static final boolean isPackageFilename(String name) {
3780 return name != null && name.endsWith(".apk");
3781 }
3782
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003783 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
3784 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
3785 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
3786 return true;
3787 }
3788 }
3789 return false;
3790 }
3791
3792 private void updatePermissionsLP(String changingPkg,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07003793 PackageParser.Package pkgInfo, boolean grantPermissions,
3794 boolean replace, boolean replaceAll) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 // Make sure there are no dangling permission trees.
3796 Iterator<BasePermission> it = mSettings.mPermissionTrees
3797 .values().iterator();
3798 while (it.hasNext()) {
3799 BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003800 if (bp.packageSetting == null) {
3801 // We may not yet have parsed the package, so just see if
3802 // we still know about its settings.
3803 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3804 }
3805 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003806 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 + " from package " + bp.sourcePackage);
3808 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003809 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3810 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3811 Slog.i(TAG, "Removing old permission tree: " + bp.name
3812 + " from package " + bp.sourcePackage);
3813 grantPermissions = true;
3814 it.remove();
3815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 }
3817 }
3818
3819 // Make sure all dynamic permissions have been assigned to a package,
3820 // and make sure there are no dangling permissions.
3821 it = mSettings.mPermissions.values().iterator();
3822 while (it.hasNext()) {
3823 BasePermission bp = it.next();
3824 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3825 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3826 + bp.name + " pkg=" + bp.sourcePackage
3827 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003828 if (bp.packageSetting == null && bp.pendingInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 BasePermission tree = findPermissionTreeLP(bp.name);
3830 if (tree != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003831 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 bp.perm = new PackageParser.Permission(tree.perm.owner,
3833 new PermissionInfo(bp.pendingInfo));
3834 bp.perm.info.packageName = tree.perm.info.packageName;
3835 bp.perm.info.name = bp.name;
3836 bp.uid = tree.uid;
3837 }
3838 }
3839 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003840 if (bp.packageSetting == null) {
3841 // We may not yet have parsed the package, so just see if
3842 // we still know about its settings.
3843 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3844 }
3845 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003846 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 + " from package " + bp.sourcePackage);
3848 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003849 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3850 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3851 Slog.i(TAG, "Removing old permission: " + bp.name
3852 + " from package " + bp.sourcePackage);
3853 grantPermissions = true;
3854 it.remove();
3855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 }
3857 }
3858
3859 // Now update the permissions for all packages, in particular
3860 // replace the granted permissions of the system packages.
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003861 if (grantPermissions) {
3862 for (PackageParser.Package pkg : mPackages.values()) {
3863 if (pkg != pkgInfo) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07003864 grantPermissionsLP(pkg, replaceAll);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003865 }
3866 }
3867 }
3868
3869 if (pkgInfo != null) {
3870 grantPermissionsLP(pkgInfo, replace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 }
3872 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3875 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3876 if (ps == null) {
3877 return;
3878 }
3879 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003880 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 if (replace) {
3883 ps.permissionsFixed = false;
3884 if (gp == ps) {
3885 gp.grantedPermissions.clear();
3886 gp.gids = mGlobalGids;
3887 }
3888 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 if (gp.gids == null) {
3891 gp.gids = mGlobalGids;
3892 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 final int N = pkg.requestedPermissions.size();
3895 for (int i=0; i<N; i++) {
3896 String name = pkg.requestedPermissions.get(i);
3897 BasePermission bp = mSettings.mPermissions.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 if (false) {
3899 if (gp != ps) {
3900 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003901 + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 }
3903 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003904 if (bp != null && bp.packageSetting != null) {
3905 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003907 boolean allowedSig = false;
3908 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3909 || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07003911 } else if (bp.packageSetting == null) {
3912 // This permission is invalid; skip it.
3913 allowed = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003914 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3915 || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003916 allowed = (checkSignaturesLP(
3917 bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003918 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003919 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 == PackageManager.SIGNATURE_MATCH);
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003921 if (!allowed && bp.protectionLevel
3922 == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Kenny Root85387d72010-08-26 10:13:11 -07003923 if (isSystemApp(pkg)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 // For updated system applications, the signatureOrSystem permission
3925 // is granted only if it had been defined by the original application.
Kenny Root85387d72010-08-26 10:13:11 -07003926 if (isUpdatedSystemApp(pkg)) {
Dianne Hackborn2fe979f2010-10-08 15:07:17 -07003927 PackageSetting sysPs = mSettings.getDisabledSystemPkg(
3928 pkg.packageName);
3929 final GrantedPermissions origGp = sysPs.sharedUser != null
3930 ? sysPs.sharedUser : sysPs;
3931 if (origGp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 allowed = true;
3933 } else {
3934 allowed = false;
3935 }
3936 } else {
3937 allowed = true;
3938 }
3939 }
3940 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003941 if (allowed) {
3942 allowedSig = true;
3943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 } else {
3945 allowed = false;
3946 }
3947 if (false) {
3948 if (gp != ps) {
3949 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3950 }
3951 }
3952 if (allowed) {
3953 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3954 && ps.permissionsFixed) {
3955 // If this is an existing, non-system package, then
3956 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07003957 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003959 // Except... if this is a permission that was added
3960 // to the platform (note: need to only do this when
3961 // updating the platform).
3962 final int NP = PackageParser.NEW_PERMISSIONS.length;
3963 for (int ip=0; ip<NP; ip++) {
3964 final PackageParser.NewPermissionInfo npi
3965 = PackageParser.NEW_PERMISSIONS[ip];
3966 if (npi.name.equals(perm)
3967 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3968 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07003969 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003970 + pkg.packageName);
3971 break;
3972 }
3973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003974 }
3975 }
3976 if (allowed) {
3977 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003978 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 gp.grantedPermissions.add(perm);
3980 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07003981 } else if (!ps.haveGids) {
3982 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
3984 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003985 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 + " to package " + pkg.packageName
3987 + " because it was previously installed without");
3988 }
3989 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003990 if (gp.grantedPermissions.remove(perm)) {
3991 changedPermission = true;
3992 gp.gids = removeInts(gp.gids, bp.gids);
3993 Slog.i(TAG, "Un-granting permission " + perm
3994 + " from package " + pkg.packageName
3995 + " (protectionLevel=" + bp.protectionLevel
3996 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3997 + ")");
3998 } else {
3999 Slog.w(TAG, "Not granting permission " + perm
4000 + " to package " + pkg.packageName
4001 + " (protectionLevel=" + bp.protectionLevel
4002 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4003 + ")");
4004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 }
4006 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004007 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 + " in package " + pkg.packageName);
4009 }
4010 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004011
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004012 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004013 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4014 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 // This is the first that we have heard about this package, so the
4016 // permissions we have now selected are fixed until explicitly
4017 // changed.
4018 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004020 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 private final class ActivityIntentResolver
4024 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02004025 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004027 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 }
4029
Mihai Preda074edef2009-05-18 17:13:31 +02004030 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004032 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4034 }
4035
Mihai Predaeae850c2009-05-13 10:13:48 +02004036 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4037 ArrayList<PackageParser.Activity> packageActivities) {
4038 if (packageActivities == null) {
4039 return null;
4040 }
4041 mFlags = flags;
4042 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4043 int N = packageActivities.size();
4044 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4045 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004046
4047 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004048 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004049 intentFilters = packageActivities.get(i).intents;
4050 if (intentFilters != null && intentFilters.size() > 0) {
4051 listCut.add(intentFilters);
4052 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004053 }
4054 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4055 }
4056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 public final void addActivity(PackageParser.Activity a, String type) {
Kenny Root502e9a42011-01-10 13:48:15 -08004058 final boolean systemApp = isSystemApp(a.info.applicationInfo);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004059 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 if (SHOW_INFO || Config.LOGV) Log.v(
4061 TAG, " " + type + " " +
4062 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4063 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4064 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004065 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
Kenny Root502e9a42011-01-10 13:48:15 -08004067 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
4068 intent.setPriority(0);
4069 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
4070 + a.className + " with priority > 0, forcing to 0");
4071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 if (SHOW_INFO || Config.LOGV) {
4073 Log.v(TAG, " IntentFilter:");
4074 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4075 }
4076 if (!intent.debugCheck()) {
4077 Log.w(TAG, "==> For Activity " + a.info.name);
4078 }
4079 addFilter(intent);
4080 }
4081 }
4082
4083 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004084 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 if (SHOW_INFO || Config.LOGV) Log.v(
4086 TAG, " " + type + " " +
4087 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4088 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4089 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004090 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
4092 if (SHOW_INFO || Config.LOGV) {
4093 Log.v(TAG, " IntentFilter:");
4094 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4095 }
4096 removeFilter(intent);
4097 }
4098 }
4099
4100 @Override
4101 protected boolean allowFilterResult(
4102 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4103 ActivityInfo filterAi = filter.activity.info;
4104 for (int i=dest.size()-1; i>=0; i--) {
4105 ActivityInfo destAi = dest.get(i).activityInfo;
4106 if (destAi.name == filterAi.name
4107 && destAi.packageName == filterAi.packageName) {
4108 return false;
4109 }
4110 }
4111 return true;
4112 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 @Override
Dianne Hackborne7f97212011-02-24 14:40:20 -08004115 protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter) {
4116 PackageParser.Package p = filter.activity.owner;
4117 if (p != null) {
4118 PackageSetting ps = (PackageSetting)p.mExtras;
4119 if (ps != null) {
4120 return ps.stopped;
4121 }
4122 }
4123 return false;
4124 }
4125
4126 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004127 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4128 return info.activity.owner.packageName;
4129 }
4130
4131 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
4133 int match) {
4134 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
4135 return null;
4136 }
4137 final PackageParser.Activity activity = info.activity;
4138 if (mSafeMode && (activity.info.applicationInfo.flags
4139 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4140 return null;
4141 }
4142 final ResolveInfo res = new ResolveInfo();
4143 res.activityInfo = PackageParser.generateActivityInfo(activity,
4144 mFlags);
4145 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4146 res.filter = info;
4147 }
4148 res.priority = info.getPriority();
4149 res.preferredOrder = activity.owner.mPreferredOrder;
4150 //System.out.println("Result: " + res.activityInfo.className +
4151 // " = " + res.priority);
4152 res.match = match;
4153 res.isDefault = info.hasDefault;
4154 res.labelRes = info.labelRes;
4155 res.nonLocalizedLabel = info.nonLocalizedLabel;
4156 res.icon = info.icon;
4157 return res;
4158 }
4159
4160 @Override
4161 protected void sortResults(List<ResolveInfo> results) {
4162 Collections.sort(results, mResolvePrioritySorter);
4163 }
4164
4165 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004166 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004168 out.print(prefix); out.print(
4169 Integer.toHexString(System.identityHashCode(filter.activity)));
4170 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004171 out.print(filter.activity.getComponentShortName());
4172 out.print(" filter ");
4173 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 }
4175
4176// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4177// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4178// final List<ResolveInfo> retList = Lists.newArrayList();
4179// while (i.hasNext()) {
4180// final ResolveInfo resolveInfo = i.next();
4181// if (isEnabledLP(resolveInfo.activityInfo)) {
4182// retList.add(resolveInfo);
4183// }
4184// }
4185// return retList;
4186// }
4187
4188 // Keys are String (activity class name), values are Activity.
4189 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4190 = new HashMap<ComponentName, PackageParser.Activity>();
4191 private int mFlags;
4192 }
4193
4194 private final class ServiceIntentResolver
4195 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02004196 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004198 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004199 }
4200
Mihai Preda074edef2009-05-18 17:13:31 +02004201 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004203 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4205 }
4206
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07004207 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4208 ArrayList<PackageParser.Service> packageServices) {
4209 if (packageServices == null) {
4210 return null;
4211 }
4212 mFlags = flags;
4213 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4214 int N = packageServices.size();
4215 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4216 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4217
4218 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4219 for (int i = 0; i < N; ++i) {
4220 intentFilters = packageServices.get(i).intents;
4221 if (intentFilters != null && intentFilters.size() > 0) {
4222 listCut.add(intentFilters);
4223 }
4224 }
4225 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4226 }
4227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004229 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 if (SHOW_INFO || Config.LOGV) Log.v(
4231 TAG, " " + (s.info.nonLocalizedLabel != null
4232 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4233 if (SHOW_INFO || Config.LOGV) Log.v(
4234 TAG, " Class=" + s.info.name);
4235 int NI = s.intents.size();
4236 int j;
4237 for (j=0; j<NI; j++) {
4238 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4239 if (SHOW_INFO || Config.LOGV) {
4240 Log.v(TAG, " IntentFilter:");
4241 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4242 }
4243 if (!intent.debugCheck()) {
4244 Log.w(TAG, "==> For Service " + s.info.name);
4245 }
4246 addFilter(intent);
4247 }
4248 }
4249
4250 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004251 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004252 if (SHOW_INFO || Config.LOGV) Log.v(
4253 TAG, " " + (s.info.nonLocalizedLabel != null
4254 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4255 if (SHOW_INFO || Config.LOGV) Log.v(
4256 TAG, " Class=" + s.info.name);
4257 int NI = s.intents.size();
4258 int j;
4259 for (j=0; j<NI; j++) {
4260 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4261 if (SHOW_INFO || Config.LOGV) {
4262 Log.v(TAG, " IntentFilter:");
4263 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4264 }
4265 removeFilter(intent);
4266 }
4267 }
4268
4269 @Override
4270 protected boolean allowFilterResult(
4271 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4272 ServiceInfo filterSi = filter.service.info;
4273 for (int i=dest.size()-1; i>=0; i--) {
4274 ServiceInfo destAi = dest.get(i).serviceInfo;
4275 if (destAi.name == filterSi.name
4276 && destAi.packageName == filterSi.packageName) {
4277 return false;
4278 }
4279 }
4280 return true;
4281 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 @Override
Dianne Hackborne7f97212011-02-24 14:40:20 -08004284 protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter) {
4285 PackageParser.Package p = filter.service.owner;
4286 if (p != null) {
4287 PackageSetting ps = (PackageSetting)p.mExtras;
4288 if (ps != null) {
4289 return ps.stopped;
4290 }
4291 }
4292 return false;
4293 }
4294
4295 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004296 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
4297 return info.service.owner.packageName;
4298 }
4299
4300 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4302 int match) {
Jason parksa3cdaa52011-01-13 14:15:43 -06004303 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4305 return null;
4306 }
4307 final PackageParser.Service service = info.service;
4308 if (mSafeMode && (service.info.applicationInfo.flags
4309 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4310 return null;
4311 }
4312 final ResolveInfo res = new ResolveInfo();
4313 res.serviceInfo = PackageParser.generateServiceInfo(service,
4314 mFlags);
4315 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4316 res.filter = filter;
4317 }
4318 res.priority = info.getPriority();
4319 res.preferredOrder = service.owner.mPreferredOrder;
4320 //System.out.println("Result: " + res.activityInfo.className +
4321 // " = " + res.priority);
4322 res.match = match;
4323 res.isDefault = info.hasDefault;
4324 res.labelRes = info.labelRes;
4325 res.nonLocalizedLabel = info.nonLocalizedLabel;
4326 res.icon = info.icon;
4327 return res;
4328 }
4329
4330 @Override
4331 protected void sortResults(List<ResolveInfo> results) {
4332 Collections.sort(results, mResolvePrioritySorter);
4333 }
4334
4335 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004336 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004338 out.print(prefix); out.print(
4339 Integer.toHexString(System.identityHashCode(filter.service)));
4340 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004341 out.print(filter.service.getComponentShortName());
4342 out.print(" filter ");
4343 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
4345
4346// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4347// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4348// final List<ResolveInfo> retList = Lists.newArrayList();
4349// while (i.hasNext()) {
4350// final ResolveInfo resolveInfo = (ResolveInfo) i;
4351// if (isEnabledLP(resolveInfo.serviceInfo)) {
4352// retList.add(resolveInfo);
4353// }
4354// }
4355// return retList;
4356// }
4357
4358 // Keys are String (activity class name), values are Activity.
4359 private final HashMap<ComponentName, PackageParser.Service> mServices
4360 = new HashMap<ComponentName, PackageParser.Service>();
4361 private int mFlags;
4362 };
4363
4364 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4365 new Comparator<ResolveInfo>() {
4366 public int compare(ResolveInfo r1, ResolveInfo r2) {
4367 int v1 = r1.priority;
4368 int v2 = r2.priority;
4369 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4370 if (v1 != v2) {
4371 return (v1 > v2) ? -1 : 1;
4372 }
4373 v1 = r1.preferredOrder;
4374 v2 = r2.preferredOrder;
4375 if (v1 != v2) {
4376 return (v1 > v2) ? -1 : 1;
4377 }
4378 if (r1.isDefault != r2.isDefault) {
4379 return r1.isDefault ? -1 : 1;
4380 }
4381 v1 = r1.match;
4382 v2 = r2.match;
4383 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4384 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4385 }
4386 };
4387
4388 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4389 new Comparator<ProviderInfo>() {
4390 public int compare(ProviderInfo p1, ProviderInfo p2) {
4391 final int v1 = p1.initOrder;
4392 final int v2 = p2.initOrder;
4393 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4394 }
4395 };
4396
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004397 private static final void sendPackageBroadcast(String action, String pkg,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004398 Bundle extras, String targetPkg, IIntentReceiver finishedReceiver) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 IActivityManager am = ActivityManagerNative.getDefault();
4400 if (am != null) {
4401 try {
4402 final Intent intent = new Intent(action,
4403 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4404 if (extras != null) {
4405 intent.putExtras(extras);
4406 }
Dianne Hackborne7f97212011-02-24 14:40:20 -08004407 if (targetPkg != null) {
4408 intent.setPackage(targetPkg);
4409 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004410 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004411 am.broadcastIntent(null, intent, null, finishedReceiver,
4412 0, null, null, null, finishedReceiver != null, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 } catch (RemoteException ex) {
4414 }
4415 }
4416 }
Kenny Root300c13a2011-01-18 13:04:40 -08004417
4418 /**
4419 * Check if the external storage media is available. This is true if there
4420 * is a mounted external storage medium or if the external storage is
4421 * emulated.
4422 */
4423 private boolean isExternalMediaAvailable() {
4424 return mMediaMounted || Environment.isExternalStorageEmulated();
4425 }
4426
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004427 public String nextPackageToClean(String lastPackage) {
4428 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08004429 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004430 // If the external storage is no longer mounted at this point,
4431 // the caller may not have been able to delete all of this
4432 // packages files and can not delete any more. Bail.
4433 return null;
4434 }
4435 if (lastPackage != null) {
4436 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4437 }
4438 return mSettings.mPackagesToBeCleaned.size() > 0
4439 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4440 }
4441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004442
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004443 void schedulePackageCleaning(String packageName) {
4444 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4445 }
4446
4447 void startCleaningPackages() {
4448 synchronized (mPackages) {
Kenny Root300c13a2011-01-18 13:04:40 -08004449 if (!isExternalMediaAvailable()) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004450 return;
4451 }
4452 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4453 return;
4454 }
4455 }
4456 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4457 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4458 IActivityManager am = ActivityManagerNative.getDefault();
4459 if (am != null) {
4460 try {
4461 am.startService(null, intent, null);
4462 } catch (RemoteException e) {
4463 }
4464 }
4465 }
4466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 private final class AppDirObserver extends FileObserver {
4468 public AppDirObserver(String path, int mask, boolean isrom) {
4469 super(path, mask);
4470 mRootDir = path;
4471 mIsRom = isrom;
4472 }
4473
4474 public void onEvent(int event, String path) {
4475 String removedPackage = null;
4476 int removedUid = -1;
4477 String addedPackage = null;
4478 int addedUid = -1;
4479
4480 synchronized (mInstallLock) {
4481 String fullPathStr = null;
4482 File fullPath = null;
4483 if (path != null) {
4484 fullPath = new File(mRootDir, path);
4485 fullPathStr = fullPath.getPath();
4486 }
4487
4488 if (Config.LOGV) Log.v(
4489 TAG, "File " + fullPathStr + " changed: "
4490 + Integer.toHexString(event));
4491
4492 if (!isPackageFilename(path)) {
4493 if (Config.LOGV) Log.v(
4494 TAG, "Ignoring change of non-package file: " + fullPathStr);
4495 return;
4496 }
4497
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004498 // Ignore packages that are being installed or
4499 // have just been installed.
4500 if (ignoreCodePath(fullPathStr)) {
4501 return;
4502 }
4503 PackageParser.Package p = null;
4504 synchronized (mPackages) {
4505 p = mAppDirs.get(fullPathStr);
4506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004508 if (p != null) {
4509 removePackageLI(p, true);
4510 removedPackage = p.applicationInfo.packageName;
4511 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004512 }
4513 }
4514
4515 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004517 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004518 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
4519 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 PackageParser.PARSE_CHATTY |
4521 PackageParser.PARSE_MUST_BE_APK,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07004522 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
4523 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 if (p != null) {
4525 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004526 updatePermissionsLP(p.packageName, p,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07004527 p.permissions.size() > 0, false, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 }
4529 addedPackage = p.applicationInfo.packageName;
4530 addedUid = p.applicationInfo.uid;
4531 }
4532 }
4533 }
4534
4535 synchronized (mPackages) {
4536 mSettings.writeLP();
4537 }
4538 }
4539
4540 if (removedPackage != null) {
4541 Bundle extras = new Bundle(1);
4542 extras.putInt(Intent.EXTRA_UID, removedUid);
4543 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004544 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004545 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 }
4547 if (addedPackage != null) {
4548 Bundle extras = new Bundle(1);
4549 extras.putInt(Intent.EXTRA_UID, addedUid);
Dianne Hackbornecb0e632010-04-07 20:22:55 -07004550 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
Dianne Hackborne7f97212011-02-24 14:40:20 -08004551 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 }
4553 }
4554
4555 private final String mRootDir;
4556 private final boolean mIsRom;
4557 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 /* Called when a downloaded package installation has been confirmed by the user */
4560 public void installPackage(
4561 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004562 installPackage(packageURI, observer, flags, null);
4563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004564
Jacek Surazski65e13172009-04-28 15:26:38 +02004565 /* Called when a downloaded package installation has been confirmed by the user */
4566 public void installPackage(
4567 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4568 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 mContext.enforceCallingOrSelfPermission(
4570 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004571
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004572 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004573 msg.obj = new InstallParams(packageURI, observer, flags,
4574 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004575 mHandler.sendMessage(msg);
4576 }
4577
Christopher Tate1bb69062010-02-19 17:02:12 -08004578 public void finishPackageInstall(int token) {
4579 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4580 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4581 mHandler.sendMessage(msg);
4582 }
4583
Dianne Hackborn880119b2010-11-18 22:26:40 -08004584 public void setInstallerPackageName(String targetPackage,
4585 String installerPackageName) {
4586 PackageSetting pkgSetting;
4587 final int uid = Binder.getCallingUid();
4588 final int permission = mContext.checkCallingPermission(
4589 android.Manifest.permission.INSTALL_PACKAGES);
4590 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
4591 synchronized (mPackages) {
4592 PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
4593 if (targetPackageSetting == null) {
4594 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
4595 }
4596
4597 PackageSetting installerPackageSetting;
4598 if (installerPackageName != null) {
4599 installerPackageSetting = mSettings.mPackages.get(installerPackageName);
4600 if (installerPackageSetting == null) {
4601 throw new IllegalArgumentException("Unknown installer package: "
4602 + installerPackageName);
4603 }
4604 } else {
4605 installerPackageSetting = null;
4606 }
4607
4608 Signature[] callerSignature;
4609 Object obj = mSettings.getUserIdLP(uid);
4610 if (obj != null) {
4611 if (obj instanceof SharedUserSetting) {
4612 callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
4613 } else if (obj instanceof PackageSetting) {
4614 callerSignature = ((PackageSetting)obj).signatures.mSignatures;
4615 } else {
4616 throw new SecurityException("Bad object " + obj + " for uid " + uid);
4617 }
4618 } else {
4619 throw new SecurityException("Unknown calling uid " + uid);
4620 }
4621
4622 // Verify: can't set installerPackageName to a package that is
4623 // not signed with the same cert as the caller.
4624 if (installerPackageSetting != null) {
4625 if (checkSignaturesLP(callerSignature,
4626 installerPackageSetting.signatures.mSignatures)
4627 != PackageManager.SIGNATURE_MATCH) {
4628 throw new SecurityException(
4629 "Caller does not have same cert as new installer package "
4630 + installerPackageName);
4631 }
4632 }
4633
4634 // Verify: if target already has an installer package, it must
4635 // be signed with the same cert as the caller.
4636 if (targetPackageSetting.installerPackageName != null) {
4637 PackageSetting setting = mSettings.mPackages.get(
4638 targetPackageSetting.installerPackageName);
4639 // If the currently set package isn't valid, then it's always
4640 // okay to change it.
4641 if (setting != null) {
4642 if (checkSignaturesLP(callerSignature,
4643 setting.signatures.mSignatures)
4644 != PackageManager.SIGNATURE_MATCH) {
4645 throw new SecurityException(
4646 "Caller does not have same cert as old installer package "
4647 + targetPackageSetting.installerPackageName);
4648 }
4649 }
4650 }
4651
4652 // Okay!
4653 targetPackageSetting.installerPackageName = installerPackageName;
4654 scheduleWriteSettingsLocked();
4655 }
4656 }
4657
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004658 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 // Queue up an async operation since the package installation may take a little while.
4660 mHandler.post(new Runnable() {
4661 public void run() {
4662 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004663 // Result object to be returned
4664 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004665 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004666 res.uid = -1;
4667 res.pkg = null;
4668 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004669 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004670 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004671 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004672 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004673 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004674 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004676
4677 // A restore should be performed at this point if (a) the install
4678 // succeeded, (b) the operation is not an update, and (c) the new
4679 // package has a backupAgent defined.
4680 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004681 boolean doRestore = (!update
4682 && res.pkg != null
4683 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004684
4685 // Set up the post-install work request bookkeeping. This will be used
4686 // and cleaned up by the post-install event handling regardless of whether
4687 // there's a restore pass performed. Token values are >= 1.
4688 int token;
4689 if (mNextInstallToken < 0) mNextInstallToken = 1;
4690 token = mNextInstallToken++;
4691
4692 PostInstallData data = new PostInstallData(args, res);
4693 mRunningInstalls.put(token, data);
4694 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4695
4696 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4697 // Pass responsibility to the Backup Manager. It will perform a
4698 // restore if appropriate, then pass responsibility back to the
4699 // Package Manager to run the post-install observer callbacks
4700 // and broadcasts.
4701 IBackupManager bm = IBackupManager.Stub.asInterface(
4702 ServiceManager.getService(Context.BACKUP_SERVICE));
4703 if (bm != null) {
4704 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4705 + " to BM for possible restore");
4706 try {
4707 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4708 } catch (RemoteException e) {
4709 // can't happen; the backup manager is local
4710 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004711 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08004712 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004713 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004714 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004715 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08004716 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004718 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004719
4720 if (!doRestore) {
4721 // No restore possible, or the Backup Manager was mysteriously not
4722 // available -- just fire the post-install work request directly.
4723 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4724 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4725 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004726 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 }
4728 });
4729 }
4730
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004731 abstract class HandlerParams {
4732 final static int MAX_RETRIES = 4;
4733 int retry = 0;
4734 final void startCopy() {
4735 try {
4736 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
4737 retry++;
4738 if (retry > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004739 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004740 mHandler.sendEmptyMessage(MCS_GIVE_UP);
4741 handleServiceError();
4742 return;
4743 } else {
4744 handleStartCopy();
4745 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
4746 mHandler.sendEmptyMessage(MCS_UNBIND);
4747 }
4748 } catch (RemoteException e) {
4749 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
4750 mHandler.sendEmptyMessage(MCS_RECONNECT);
4751 }
4752 handleReturnCode();
4753 }
4754
4755 final void serviceError() {
4756 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
4757 handleServiceError();
4758 handleReturnCode();
4759 }
4760 abstract void handleStartCopy() throws RemoteException;
4761 abstract void handleServiceError();
4762 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004763 }
4764
Kenny Root366949c2011-01-14 17:18:14 -08004765 class MeasureParams extends HandlerParams {
4766 private final PackageStats mStats;
4767 private boolean mSuccess;
4768
4769 private final IPackageStatsObserver mObserver;
4770
4771 public MeasureParams(PackageStats stats, boolean success,
4772 IPackageStatsObserver observer) {
4773 mObserver = observer;
4774 mStats = stats;
4775 mSuccess = success;
4776 }
4777
4778 @Override
4779 void handleStartCopy() throws RemoteException {
4780 final boolean mounted;
4781
4782 if (Environment.isExternalStorageEmulated()) {
4783 mounted = true;
4784 } else {
4785 final String status = Environment.getExternalStorageState();
4786
4787 mounted = status.equals(Environment.MEDIA_MOUNTED)
4788 || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
4789 }
4790
4791 if (mounted) {
4792 final File externalCacheDir = Environment
4793 .getExternalStorageAppCacheDirectory(mStats.packageName);
4794 final long externalCacheSize = mContainerService
4795 .calculateDirectorySize(externalCacheDir.getPath());
4796 mStats.externalCacheSize = externalCacheSize;
4797
4798 final File externalDataDir = Environment
4799 .getExternalStorageAppDataDirectory(mStats.packageName);
4800 long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
4801 .getPath());
4802
4803 if (externalCacheDir.getParentFile().equals(externalDataDir)) {
4804 externalDataSize -= externalCacheSize;
4805 }
4806 mStats.externalDataSize = externalDataSize;
4807
4808 final File externalMediaDir = Environment
4809 .getExternalStorageAppMediaDirectory(mStats.packageName);
4810 mStats.externalMediaSize = mContainerService
Kenny Rootc7624d92011-02-23 16:25:25 -08004811 .calculateDirectorySize(externalMediaDir.getPath());
Kenny Rootbcd6c962011-01-17 11:21:49 -08004812
4813 final File externalObbDir = Environment
4814 .getExternalStorageAppObbDirectory(mStats.packageName);
4815 mStats.externalObbSize = mContainerService.calculateDirectorySize(externalObbDir
4816 .getPath());
Kenny Root366949c2011-01-14 17:18:14 -08004817 }
4818 }
4819
4820 @Override
4821 void handleReturnCode() {
4822 if (mObserver != null) {
4823 try {
4824 mObserver.onGetStatsCompleted(mStats, mSuccess);
4825 } catch (RemoteException e) {
4826 Slog.i(TAG, "Observer no longer exists.");
4827 }
4828 }
4829 }
4830
4831 @Override
4832 void handleServiceError() {
4833 Slog.e(TAG, "Could not measure application " + mStats.packageName
4834 + " external storage");
4835 }
4836 }
4837
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004838 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004839 final IPackageInstallObserver observer;
4840 int flags;
4841 final Uri packageURI;
4842 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004843 private InstallArgs mArgs;
4844 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004845 InstallParams(Uri packageURI,
4846 IPackageInstallObserver observer, int flags,
4847 String installerPackageName) {
4848 this.packageURI = packageURI;
4849 this.flags = flags;
4850 this.observer = observer;
4851 this.installerPackageName = installerPackageName;
4852 }
4853
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004854 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
4855 String packageName = pkgLite.packageName;
4856 int installLocation = pkgLite.installLocation;
4857 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
4858 synchronized (mPackages) {
4859 PackageParser.Package pkg = mPackages.get(packageName);
4860 if (pkg != null) {
4861 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
4862 // Check for updated system application.
4863 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4864 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004865 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004866 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
4867 }
4868 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4869 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004870 if (onSd) {
4871 // Install flag overrides everything.
4872 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4873 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004874 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004875 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
4876 // Application explicitly specified internal.
4877 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4878 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
4879 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004880 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004881 // Prefer previous location
Kenny Root85387d72010-08-26 10:13:11 -07004882 if (isExternal(pkg)) {
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004883 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4884 }
4885 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004886 }
4887 }
4888 } else {
4889 // Invalid install. Return error code
4890 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
4891 }
4892 }
4893 }
4894 // All the special cases have been taken care of.
4895 // Return result based on recommended install location.
4896 if (onSd) {
4897 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4898 }
4899 return pkgLite.recommendedInstallLocation;
4900 }
4901
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004902 /*
4903 * Invoke remote method to get package information and install
4904 * location values. Override install location based on default
4905 * policy if needed and then create install arguments based
4906 * on the install location.
4907 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004908 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004909 int ret = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004910 boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
4911 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004912 boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
4913 if (onInt && onSd) {
4914 // Check if both bits are set.
4915 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
4916 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4917 } else if (fwdLocked && onSd) {
4918 // Check for forward locked apps
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004919 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004920 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004921 } else {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004922 // Remote call to find out default install location
Kenny Root11128572010-10-11 10:51:32 -07004923 final PackageInfoLite pkgLite;
4924 try {
4925 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
4926 Intent.FLAG_GRANT_READ_URI_PERMISSION);
4927 pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
4928 } finally {
4929 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
4930 }
4931
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004932 int loc = pkgLite.recommendedInstallLocation;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004933 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
4934 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4935 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
4936 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4937 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004938 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4939 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
4940 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004941 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
4942 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004943 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004944 // Override with defaults if needed.
4945 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004946 if (!onSd && !onInt) {
4947 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004948 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
4949 // Set the flag to install on external media.
4950 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004951 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004952 } else {
4953 // Make sure the flag for installing on external
4954 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004955 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004956 flags &= ~PackageManager.INSTALL_EXTERNAL;
4957 }
4958 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004959 }
4960 }
4961 // Create the file args now.
4962 mArgs = createInstallArgs(this);
4963 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4964 // Create copy only if we are not in an erroneous state.
4965 // Remote call to initiate copy using temporary file
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004966 ret = mArgs.copyApk(mContainerService, true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004967 }
4968 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004969 }
4970
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004971 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004972 void handleReturnCode() {
Kenny Root6f89fa02010-07-30 16:33:47 -07004973 // If mArgs is null, then MCS couldn't be reached. When it
4974 // reconnects, it will try again to install. At that point, this
4975 // will succeed.
4976 if (mArgs != null) {
4977 processPendingInstall(mArgs, mRet);
4978 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004979 }
4980
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004981 @Override
4982 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004983 mArgs = createInstallArgs(this);
4984 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004985 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004986 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004987
4988 /*
4989 * Utility class used in movePackage api.
4990 * srcArgs and targetArgs are not set for invalid flags and make
4991 * sure to do null checks when invoking methods on them.
4992 * We probably want to return ErrorPrams for both failed installs
4993 * and moves.
4994 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004995 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004996 final IPackageMoveObserver observer;
4997 final int flags;
4998 final String packageName;
4999 final InstallArgs srcArgs;
5000 final InstallArgs targetArgs;
5001 int mRet;
Kenny Root85387d72010-08-26 10:13:11 -07005002
5003 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
5004 String packageName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005005 this.srcArgs = srcArgs;
5006 this.observer = observer;
5007 this.flags = flags;
5008 this.packageName = packageName;
5009 if (srcArgs != null) {
5010 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
Kenny Root85387d72010-08-26 10:13:11 -07005011 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005012 } else {
5013 targetArgs = null;
5014 }
5015 }
5016
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005017 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005018 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5019 // Check for storage space on target medium
5020 if (!targetArgs.checkFreeStorage(mContainerService)) {
5021 Log.w(TAG, "Insufficient storage to install");
5022 return;
5023 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005024 // Create the file args now.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005025 mRet = targetArgs.copyApk(mContainerService, false);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005026 targetArgs.doPreInstall(mRet);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005027 if (DEBUG_SD_INSTALL) {
5028 StringBuilder builder = new StringBuilder();
5029 if (srcArgs != null) {
5030 builder.append("src: ");
5031 builder.append(srcArgs.getCodePath());
5032 }
5033 if (targetArgs != null) {
5034 builder.append(" target : ");
5035 builder.append(targetArgs.getCodePath());
5036 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005037 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005038 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005039 }
5040
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005041 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005042 void handleReturnCode() {
5043 targetArgs.doPostInstall(mRet);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005044 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
5045 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
5046 currentStatus = PackageManager.MOVE_SUCCEEDED;
5047 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
5048 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
5049 }
5050 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005051 }
5052
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005053 @Override
5054 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005055 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005056 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005057 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005058
5059 private InstallArgs createInstallArgs(InstallParams params) {
5060 if (installOnSd(params.flags)) {
5061 return new SdInstallArgs(params);
5062 } else {
5063 return new FileInstallArgs(params);
5064 }
5065 }
5066
Kenny Root85387d72010-08-26 10:13:11 -07005067 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
5068 String nativeLibraryPath) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005069 if (installOnSd(flags)) {
Kenny Root85387d72010-08-26 10:13:11 -07005070 return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005071 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005072 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005073 }
5074 }
5075
Kenny Root85387d72010-08-26 10:13:11 -07005076 // Used by package mover
5077 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005078 if (installOnSd(flags)) {
5079 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
5080 return new SdInstallArgs(packageURI, cid);
5081 } else {
Kenny Root85387d72010-08-26 10:13:11 -07005082 return new FileInstallArgs(packageURI, pkgName, dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005083 }
5084 }
5085
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005086 static abstract class InstallArgs {
5087 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005088 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005089 final int flags;
5090 final Uri packageURI;
5091 final String installerPackageName;
5092
5093 InstallArgs(Uri packageURI,
5094 IPackageInstallObserver observer, int flags,
5095 String installerPackageName) {
5096 this.packageURI = packageURI;
5097 this.flags = flags;
5098 this.observer = observer;
5099 this.installerPackageName = installerPackageName;
5100 }
5101
5102 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005103 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005104 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005105 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005106 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005107 abstract String getCodePath();
5108 abstract String getResourcePath();
Kenny Root85387d72010-08-26 10:13:11 -07005109 abstract String getNativeLibraryPath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005110 // Need installer lock especially for dex file removal.
5111 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005112 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005113 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005114 }
5115
5116 class FileInstallArgs extends InstallArgs {
5117 File installDir;
5118 String codeFileName;
5119 String resourceFileName;
Kenny Root85387d72010-08-26 10:13:11 -07005120 String libraryPath;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005121 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005122
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005123 FileInstallArgs(InstallParams params) {
5124 super(params.packageURI, params.observer,
5125 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005126 }
5127
Kenny Root85387d72010-08-26 10:13:11 -07005128 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005129 super(null, null, 0, null);
5130 File codeFile = new File(fullCodePath);
5131 installDir = codeFile.getParentFile();
5132 codeFileName = fullCodePath;
5133 resourceFileName = fullResourcePath;
Kenny Root85387d72010-08-26 10:13:11 -07005134 libraryPath = nativeLibraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005135 }
5136
Kenny Root85387d72010-08-26 10:13:11 -07005137 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005138 super(packageURI, null, 0, null);
Kenny Root85387d72010-08-26 10:13:11 -07005139 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005140 String apkName = getNextCodePath(null, pkgName, ".apk");
5141 codeFileName = new File(installDir, apkName + ".apk").getPath();
5142 resourceFileName = getResourcePathFromCodePath();
Kenny Root85387d72010-08-26 10:13:11 -07005143 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005144 }
5145
Kenny Root11128572010-10-11 10:51:32 -07005146 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5147 try {
5148 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5149 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5150 return imcs.checkFreeStorage(false, packageURI);
5151 } finally {
5152 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5153 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005154 }
5155
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005156 String getCodePath() {
5157 return codeFileName;
5158 }
5159
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005160 void createCopyFile() {
Kenny Root85387d72010-08-26 10:13:11 -07005161 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005162 codeFileName = createTempPackageFile(installDir).getPath();
5163 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005164 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005165 }
5166
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005167 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005168 if (temp) {
5169 // Generate temp file name
5170 createCopyFile();
5171 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005172 // Get a ParcelFileDescriptor to write to the output file
5173 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005174 if (!created) {
5175 try {
5176 codeFile.createNewFile();
5177 // Set permissions
5178 if (!setPermissions()) {
5179 // Failed setting permissions.
5180 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5181 }
5182 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005183 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005184 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5185 }
5186 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005187 ParcelFileDescriptor out = null;
5188 try {
Kenny Root85387d72010-08-26 10:13:11 -07005189 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005190 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005191 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005192 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5193 }
5194 // Copy the resource now
5195 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5196 try {
Kenny Root11128572010-10-11 10:51:32 -07005197 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5198 Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005199 if (imcs.copyResource(packageURI, out)) {
5200 ret = PackageManager.INSTALL_SUCCEEDED;
5201 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005202 } finally {
5203 try { if (out != null) out.close(); } catch (IOException e) {}
Kenny Root11128572010-10-11 10:51:32 -07005204 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005205 }
Kenny Root85387d72010-08-26 10:13:11 -07005206
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005207 return ret;
5208 }
5209
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005210 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005211 if (status != PackageManager.INSTALL_SUCCEEDED) {
5212 cleanUp();
5213 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005214 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005215 }
5216
5217 boolean doRename(int status, final String pkgName, String oldCodePath) {
5218 if (status != PackageManager.INSTALL_SUCCEEDED) {
5219 cleanUp();
5220 return false;
5221 } else {
5222 // Rename based on packageName
5223 File codeFile = new File(getCodePath());
5224 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
5225 File desFile = new File(installDir, apkName + ".apk");
5226 if (!codeFile.renameTo(desFile)) {
5227 return false;
5228 }
5229 // Reset paths since the file has been renamed.
5230 codeFileName = desFile.getPath();
5231 resourceFileName = getResourcePathFromCodePath();
5232 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005233 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005234 // Failed setting permissions.
5235 return false;
5236 }
5237 return true;
5238 }
5239 }
5240
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005241 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005242 if (status != PackageManager.INSTALL_SUCCEEDED) {
5243 cleanUp();
5244 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005245 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005246 }
5247
5248 String getResourcePath() {
5249 return resourceFileName;
5250 }
5251
5252 String getResourcePathFromCodePath() {
5253 String codePath = getCodePath();
5254 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
5255 String apkNameOnly = getApkName(codePath);
5256 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
5257 } else {
5258 return codePath;
5259 }
5260 }
5261
Kenny Root85387d72010-08-26 10:13:11 -07005262 @Override
5263 String getNativeLibraryPath() {
5264 return libraryPath;
5265 }
5266
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005267 private boolean cleanUp() {
5268 boolean ret = true;
5269 String sourceDir = getCodePath();
5270 String publicSourceDir = getResourcePath();
5271 if (sourceDir != null) {
5272 File sourceFile = new File(sourceDir);
5273 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005274 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005275 ret = false;
5276 }
5277 // Delete application's code and resources
5278 sourceFile.delete();
5279 }
5280 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
5281 final File publicSourceFile = new File(publicSourceDir);
5282 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005283 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005284 }
5285 if (publicSourceFile.exists()) {
5286 publicSourceFile.delete();
5287 }
5288 }
5289 return ret;
5290 }
5291
5292 void cleanUpResourcesLI() {
5293 String sourceDir = getCodePath();
5294 if (cleanUp() && mInstaller != null) {
5295 int retCode = mInstaller.rmdex(sourceDir);
5296 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005297 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005298 + " at location "
5299 + sourceDir + ", retcode=" + retCode);
5300 // we don't consider this to be a failure of the core package deletion
5301 }
5302 }
5303 }
5304
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005305 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005306 // TODO Do this in a more elegant way later on. for now just a hack
Kenny Root85387d72010-08-26 10:13:11 -07005307 if (!isFwdLocked()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005308 final int filePermissions =
5309 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
5310 |FileUtils.S_IROTH;
5311 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
5312 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005313 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005314 getCodePath()
5315 + ". The return code was: " + retCode);
5316 // TODO Define new internal error
5317 return false;
5318 }
5319 return true;
5320 }
5321 return true;
5322 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005323
5324 boolean doPostDeleteLI(boolean delete) {
Kenny Root85387d72010-08-26 10:13:11 -07005325 // XXX err, shouldn't we respect the delete flag?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005326 cleanUpResourcesLI();
5327 return true;
5328 }
Kenny Root85387d72010-08-26 10:13:11 -07005329
5330 private boolean isFwdLocked() {
5331 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
5332 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005333 }
5334
5335 class SdInstallArgs extends InstallArgs {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005336 static final String RES_FILE_NAME = "pkg.apk";
5337
Kenny Root85387d72010-08-26 10:13:11 -07005338 String cid;
5339 String packagePath;
5340 String libraryPath;
5341
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005342 SdInstallArgs(InstallParams params) {
5343 super(params.packageURI, params.observer,
5344 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005345 }
5346
Kenny Root85387d72010-08-26 10:13:11 -07005347 SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005348 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005349 // Extract cid from fullCodePath
5350 int eidx = fullCodePath.lastIndexOf("/");
5351 String subStr1 = fullCodePath.substring(0, eidx);
5352 int sidx = subStr1.lastIndexOf("/");
5353 cid = subStr1.substring(sidx+1, eidx);
Kenny Root85387d72010-08-26 10:13:11 -07005354 setCachePath(subStr1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005355 }
5356
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005357 SdInstallArgs(String cid) {
Dianne Hackbornaa77de12010-05-14 22:33:54 -07005358 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
5359 this.cid = cid;
Kenny Root85387d72010-08-26 10:13:11 -07005360 setCachePath(PackageHelper.getSdDir(cid));
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005361 }
5362
5363 SdInstallArgs(Uri packageURI, String cid) {
5364 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005365 this.cid = cid;
5366 }
5367
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005368 void createCopyFile() {
5369 cid = getTempContainerId();
5370 }
5371
Kenny Root11128572010-10-11 10:51:32 -07005372 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5373 try {
5374 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5375 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5376 return imcs.checkFreeStorage(true, packageURI);
5377 } finally {
5378 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5379 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005380 }
5381
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005382 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005383 if (temp) {
5384 createCopyFile();
5385 }
Kenny Root11128572010-10-11 10:51:32 -07005386
5387 final String newCachePath;
5388 try {
5389 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
5390 Intent.FLAG_GRANT_READ_URI_PERMISSION);
5391 newCachePath = imcs.copyResourceToContainer(packageURI, cid,
5392 getEncryptKey(), RES_FILE_NAME);
5393 } finally {
5394 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
5395 }
5396
Kenny Root85387d72010-08-26 10:13:11 -07005397 if (newCachePath != null) {
5398 setCachePath(newCachePath);
5399 return PackageManager.INSTALL_SUCCEEDED;
5400 } else {
5401 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5402 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005403 }
5404
5405 @Override
5406 String getCodePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005407 return packagePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005408 }
5409
5410 @Override
5411 String getResourcePath() {
Kenny Root85387d72010-08-26 10:13:11 -07005412 return packagePath;
5413 }
5414
5415 @Override
5416 String getNativeLibraryPath() {
5417 return libraryPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005418 }
5419
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005420 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005421 if (status != PackageManager.INSTALL_SUCCEEDED) {
5422 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005423 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005424 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005425 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005426 if (!mounted) {
Kenny Root85387d72010-08-26 10:13:11 -07005427 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
5428 Process.SYSTEM_UID);
5429 if (newCachePath != null) {
5430 setCachePath(newCachePath);
5431 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005432 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5433 }
5434 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005435 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005436 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005437 }
5438
5439 boolean doRename(int status, final String pkgName,
5440 String oldCodePath) {
5441 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005442 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005443 if (PackageHelper.isContainerMounted(cid)) {
5444 // Unmount the container
5445 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005446 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005447 return false;
5448 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005449 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005450 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07005451 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
5452 " which might be stale. Will try to clean up.");
5453 // Clean up the stale container and proceed to recreate.
5454 if (!PackageHelper.destroySdDir(newCacheId)) {
5455 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
5456 return false;
5457 }
5458 // Successfully cleaned up stale container. Try to rename again.
5459 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
5460 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
5461 + " inspite of cleaning it up.");
5462 return false;
5463 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005464 }
5465 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005466 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005467 newCachePath = PackageHelper.mountSdDir(newCacheId,
5468 getEncryptKey(), Process.SYSTEM_UID);
5469 } else {
5470 newCachePath = PackageHelper.getSdDir(newCacheId);
5471 }
5472 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005473 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005474 return false;
5475 }
5476 Log.i(TAG, "Succesfully renamed " + cid +
Kenny Root85387d72010-08-26 10:13:11 -07005477 " to " + newCacheId +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005478 " at new path: " + newCachePath);
5479 cid = newCacheId;
Kenny Root85387d72010-08-26 10:13:11 -07005480 setCachePath(newCachePath);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005481 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005482 }
5483
Kenny Root85387d72010-08-26 10:13:11 -07005484 private void setCachePath(String newCachePath) {
5485 File cachePath = new File(newCachePath);
5486 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
5487 packagePath = new File(cachePath, RES_FILE_NAME).getPath();
5488 }
5489
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005490 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005491 if (status != PackageManager.INSTALL_SUCCEEDED) {
5492 cleanUp();
5493 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005494 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005495 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005496 PackageHelper.mountSdDir(cid,
5497 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005498 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005499 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005500 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005501 }
5502
5503 private void cleanUp() {
5504 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005505 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005506 }
5507
5508 void cleanUpResourcesLI() {
5509 String sourceFile = getCodePath();
5510 // Remove dex file
5511 if (mInstaller != null) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005512 int retCode = mInstaller.rmdex(sourceFile);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005513 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005514 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005515 + " at location "
5516 + sourceFile.toString() + ", retcode=" + retCode);
5517 // we don't consider this to be a failure of the core package deletion
5518 }
5519 }
5520 cleanUp();
5521 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005522
5523 boolean matchContainer(String app) {
5524 if (cid.startsWith(app)) {
5525 return true;
5526 }
5527 return false;
5528 }
5529
5530 String getPackageName() {
5531 int idx = cid.lastIndexOf("-");
5532 if (idx == -1) {
5533 return cid;
5534 }
5535 return cid.substring(0, idx);
5536 }
5537
5538 boolean doPostDeleteLI(boolean delete) {
5539 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005540 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005541 if (mounted) {
5542 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005543 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005544 }
5545 if (ret && delete) {
5546 cleanUpResourcesLI();
5547 }
5548 return ret;
5549 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005550 };
5551
5552 // Utility method used to create code paths based on package name and available index.
5553 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
5554 String idxStr = "";
5555 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005556 // Fall back to default value of idx=1 if prefix is not
5557 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005558 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005559 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005560 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005561 if (subStr.endsWith(suffix)) {
5562 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005563 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005564 // If oldCodePath already contains prefix find out the
5565 // ending index to either increment or decrement.
5566 int sidx = subStr.lastIndexOf(prefix);
5567 if (sidx != -1) {
5568 subStr = subStr.substring(sidx + prefix.length());
5569 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005570 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5571 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005572 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005573 try {
5574 idx = Integer.parseInt(subStr);
5575 if (idx <= 1) {
5576 idx++;
5577 } else {
5578 idx--;
5579 }
5580 } catch(NumberFormatException e) {
5581 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005582 }
5583 }
5584 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005585 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005586 return prefix + idxStr;
5587 }
5588
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005589 // Utility method used to ignore ADD/REMOVE events
5590 // by directory observer.
5591 private static boolean ignoreCodePath(String fullPathStr) {
5592 String apkName = getApkName(fullPathStr);
5593 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5594 if (idx != -1 && ((idx+1) < apkName.length())) {
5595 // Make sure the package ends with a numeral
5596 String version = apkName.substring(idx+1);
5597 try {
5598 Integer.parseInt(version);
5599 return true;
5600 } catch (NumberFormatException e) {}
5601 }
5602 return false;
5603 }
5604
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005605 // Utility method that returns the relative package path with respect
5606 // to the installation directory. Like say for /data/data/com.test-1.apk
5607 // string com.test-1 is returned.
5608 static String getApkName(String codePath) {
5609 if (codePath == null) {
5610 return null;
5611 }
5612 int sidx = codePath.lastIndexOf("/");
5613 int eidx = codePath.lastIndexOf(".");
5614 if (eidx == -1) {
5615 eidx = codePath.length();
5616 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005617 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005618 return null;
5619 }
5620 return codePath.substring(sidx+1, eidx);
5621 }
5622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 class PackageInstalledInfo {
5624 String name;
5625 int uid;
5626 PackageParser.Package pkg;
5627 int returnCode;
5628 PackageRemovedInfo removedInfo;
5629 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005631 /*
5632 * Install a non-existing package.
5633 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005634 private void installNewPackageLI(PackageParser.Package pkg,
5635 int parseFlags,
5636 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005637 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005638 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005639 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005640
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08005641 boolean dataDirExists = getDataPathForPackage(pkg).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005642 res.name = pkgName;
5643 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07005644 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
5645 // A package with the same name is already installed, though
5646 // it has been renamed to an older name. The package we
5647 // are trying to install should be installed as an update to
5648 // the existing one, but that has not been requested, so bail.
5649 Slog.w(TAG, "Attempt to re-install " + pkgName
5650 + " without first uninstalling package running as "
5651 + mSettings.mRenamedPackages.get(pkgName));
5652 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5653 return;
5654 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005655 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005656 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005657 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 + " without first uninstalling.");
5659 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5660 return;
5661 }
5662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005663 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005664 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
5665 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005666 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005667 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5669 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5670 }
5671 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005672 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005673 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 res);
5675 // delete the partially installed application. the data directory will have to be
5676 // restored if it was already existing
5677 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5678 // remove package from internal structures. Note that we want deletePackageX to
5679 // delete the package data and cache directories that it created in
5680 // scanPackageLocked, unless those directories existed before we even tried to
5681 // install.
5682 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005683 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005684 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005685 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 }
5687 }
5688 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005689
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005690 private void replacePackageLI(PackageParser.Package pkg,
5691 int parseFlags,
5692 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005693 String installerPackageName, PackageInstalledInfo res) {
5694
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005695 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005696 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005697 // First find the old package info and check signatures
5698 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005699 oldPackage = mPackages.get(pkgName);
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005700 if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005701 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5703 return;
5704 }
5705 }
Kenny Root85387d72010-08-26 10:13:11 -07005706 boolean sysPkg = (isSystemApp(oldPackage));
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005707 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005708 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005710 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 }
5712 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005715 PackageParser.Package pkg,
5716 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005717 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 PackageParser.Package newPackage = null;
5719 String pkgName = deletedPackage.packageName;
5720 boolean deletedPkg = true;
5721 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005722
Jacek Surazski65e13172009-04-28 15:26:38 +02005723 String oldInstallerPackageName = null;
5724 synchronized (mPackages) {
5725 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
5726 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005727
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005728 long origUpdateTime;
5729 if (pkg.mExtras != null) {
5730 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime;
5731 } else {
5732 origUpdateTime = 0;
5733 }
5734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005736 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005737 res.removedInfo, true)) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005738 // If the existing package wasn't successfully deleted
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5740 deletedPkg = false;
5741 } else {
5742 // Successfully deleted the old package. Now proceed with re-installation
5743 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005744 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
5745 System.currentTimeMillis());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005747 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005748 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5749 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005750 }
5751 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005752 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005753 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 res);
5755 updatedSettings = true;
5756 }
5757 }
5758
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005759 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005760 // remove package from internal structures. Note that we want deletePackageX to
5761 // delete the package data and cache directories that it created in
5762 // scanPackageLocked, unless those directories existed before we even tried to
5763 // install.
5764 if(updatedSettings) {
5765 deletePackageLI(
5766 pkgName, true,
5767 PackageManager.DONT_DELETE_DATA,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07005768 res.removedInfo, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 }
5770 // Since we failed to install the new package we need to restore the old
5771 // package that we deleted.
5772 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005773 File restoreFile = new File(deletedPackage.mPath);
5774 if (restoreFile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005775 Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005776 return;
5777 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005778 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005779 boolean oldOnSd = isExternal(deletedPackage);
5780 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
5781 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5782 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005783 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
5784 | SCAN_UPDATE_TIME;
5785 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
5786 origUpdateTime) == null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005787 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
5788 return;
5789 }
5790 // Restore of old package succeeded. Update permissions.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005791 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005792 updatePermissionsLP(deletedPackage.packageName, deletedPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07005793 true, false, false);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005794 mSettings.writeLP();
5795 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005796 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005797 }
5798 }
5799 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005802 PackageParser.Package pkg,
5803 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005804 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 PackageParser.Package newPackage = null;
5806 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005807 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 PackageParser.PARSE_IS_SYSTEM;
5809 String packageName = deletedPackage.packageName;
5810 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5811 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005812 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 return;
5814 }
5815 PackageParser.Package oldPkg;
5816 PackageSetting oldPkgSetting;
5817 synchronized (mPackages) {
5818 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005819 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5821 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005822 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005823 return;
5824 }
5825 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005826
5827 killApplication(packageName, oldPkg.applicationInfo.uid);
5828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5830 res.removedInfo.removedPackage = packageName;
5831 // Remove existing system package
5832 removePackageLI(oldPkg, true);
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005833 synchronized (mPackages) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08005834 if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) {
5835 // We didn't need to disable the .apk as a current system package,
5836 // which means we are replacing another update that is already
5837 // installed. We need to make sure to delete the older one's .apk.
5838 res.removedInfo.args = createInstallArgs(isExternal(pkg)
5839 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
5840 deletedPackage.applicationInfo.sourceDir,
5841 deletedPackage.applicationInfo.publicSourceDir,
5842 deletedPackage.applicationInfo.nativeLibraryDir);
5843 } else {
5844 res.removedInfo.args = null;
5845 }
Dianne Hackborn3ec27e02010-12-16 12:41:56 -08005846 }
5847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 // Successfully disabled the old package. Now proceed with re-installation
5849 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5850 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005851 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005853 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5855 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5856 }
5857 } else {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005858 if (newPackage.mExtras != null) {
5859 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
5860 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
5861 newPkgSetting.lastUpdateTime = System.currentTimeMillis();
5862 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005863 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 updatedSettings = true;
5865 }
5866
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005867 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 // Re installation failed. Restore old information
5869 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005870 if (newPackage != null) {
5871 removePackageLI(newPackage, true);
5872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 // Add back the old system package
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005874 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 // Restore the old system information in Settings
5876 synchronized(mPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07005877 if (updatedSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005879 mSettings.setInstallerPackageName(packageName,
5880 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 }
5882 mSettings.writeLP();
5883 }
5884 }
5885 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005886
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005887 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005888 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005889 int retCode;
5890 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5891 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5892 if (retCode != 0) {
Kenny Roote2f74172010-08-04 13:35:33 -07005893 if (mNoDexOpt) {
5894 /*
5895 * If we're in an engineering build, programs are lazily run
5896 * through dexopt. If the .dex file doesn't exist yet, it
5897 * will be created when the program is run next.
5898 */
5899 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath);
5900 } else {
5901 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
5902 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5903 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005904 }
5905 }
5906 return PackageManager.INSTALL_SUCCEEDED;
5907 }
5908
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005909 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005910 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005911 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 synchronized (mPackages) {
5913 //write settings. the installStatus will be incomplete at this stage.
5914 //note that the new package setting would have already been
5915 //added to mPackages. It hasn't been persisted yet.
5916 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5917 mSettings.writeLP();
5918 }
5919
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005920 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005921 != PackageManager.INSTALL_SUCCEEDED) {
5922 // Discontinue if moving dex files failed.
5923 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005925 if((res.returnCode = setPermissionsLI(newPackage))
5926 != PackageManager.INSTALL_SUCCEEDED) {
5927 if (mInstaller != null) {
5928 mInstaller.rmdex(newPackage.mScanPath);
5929 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005930 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005932 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005935 updatePermissionsLP(newPackage.packageName, newPackage,
Dianne Hackborn92cfa102010-04-28 11:00:44 -07005936 newPackage.permissions.size() > 0, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005937 res.name = pkgName;
5938 res.uid = newPackage.applicationInfo.uid;
5939 res.pkg = newPackage;
5940 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005941 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5943 //to update install status
5944 mSettings.writeLP();
5945 }
5946 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005947
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005948 private void installPackageLI(InstallArgs args,
5949 boolean newInstall, PackageInstalledInfo res) {
5950 int pFlags = args.flags;
5951 String installerPackageName = args.installerPackageName;
5952 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005953 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005954 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005955 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005956 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005957 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005958 // Result object to be returned
5959 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5960
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005961 // Retrieve PackageSettings and parse package
5962 int parseFlags = PackageParser.PARSE_CHATTY |
5963 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5964 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5965 parseFlags |= mDefParseFlags;
5966 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5967 pp.setSeparateProcesses(mSeparateProcesses);
5968 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5969 null, mMetrics, parseFlags);
5970 if (pkg == null) {
5971 res.returnCode = pp.getParseError();
5972 return;
5973 }
5974 String pkgName = res.name = pkg.packageName;
5975 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5976 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5977 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5978 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005980 }
5981 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5982 res.returnCode = pp.getParseError();
5983 return;
5984 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005985 // Get rid of all references to package scan path via parser.
5986 pp = null;
5987 String oldCodePath = null;
5988 boolean systemApp = false;
5989 synchronized (mPackages) {
5990 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005991 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5992 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08005993 if (pkg.mOriginalPackages != null
5994 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005995 && mPackages.containsKey(oldName)) {
5996 // This package is derived from an original package,
5997 // and this device has been updating from that original
5998 // name. We must continue using the original name, so
5999 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08006000 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006001 pkgName = pkg.packageName;
6002 replace = true;
6003 } else if (mPackages.containsKey(pkgName)) {
6004 // This package, under its official name, already exists
6005 // on the device; we should replace it.
6006 replace = true;
6007 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006008 }
6009 PackageSetting ps = mSettings.mPackages.get(pkgName);
6010 if (ps != null) {
6011 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
6012 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
6013 systemApp = (ps.pkg.applicationInfo.flags &
6014 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07006015 }
6016 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006017 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006018
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006019 if (systemApp && onSd) {
6020 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006021 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006022 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
6023 return;
6024 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08006025
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006026 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
6027 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6028 return;
6029 }
6030 // Set application objects path explicitly after the rename
6031 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Kenny Root85387d72010-08-26 10:13:11 -07006032 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006033 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08006034 replacePackageLI(pkg, parseFlags, scanMode,
6035 installerPackageName, res);
6036 } else {
6037 installNewPackageLI(pkg, parseFlags, scanMode,
6038 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 }
6040 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006041
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006042 private int setPermissionsLI(PackageParser.Package newPackage) {
6043 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006044 int retCode = 0;
6045 // TODO Gross hack but fix later. Ideally move this to be a post installation
6046 // check after alloting uid.
Kenny Root85387d72010-08-26 10:13:11 -07006047 if (isForwardLocked(newPackage)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006048 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 try {
6050 extractPublicFiles(newPackage, destResourceFile);
6051 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006052 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 -08006053 " forward-locked app.");
6054 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
6055 } finally {
6056 //TODO clean up the extracted public files
6057 }
6058 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006059 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 newPackage.applicationInfo.uid);
6061 } else {
6062 final int filePermissions =
6063 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006064 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 newPackage.applicationInfo.uid);
6066 }
6067 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006068 // The permissions on the resource file was set when it was copied for
6069 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006073 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006074 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006075 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006076 // TODO Define new internal error
6077 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 }
6079 return PackageManager.INSTALL_SUCCEEDED;
6080 }
6081
Kenny Root85387d72010-08-26 10:13:11 -07006082 private static boolean isForwardLocked(PackageParser.Package pkg) {
6083 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006084 }
6085
Kenny Root85387d72010-08-26 10:13:11 -07006086 private static boolean isExternal(PackageParser.Package pkg) {
6087 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
6088 }
6089
6090 private static boolean isSystemApp(PackageParser.Package pkg) {
6091 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6092 }
6093
Kenny Root502e9a42011-01-10 13:48:15 -08006094 private static boolean isSystemApp(ApplicationInfo info) {
6095 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
6096 }
6097
Kenny Root85387d72010-08-26 10:13:11 -07006098 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
6099 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07006100 }
6101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 private void extractPublicFiles(PackageParser.Package newPackage,
6103 File publicZipFile) throws IOException {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006104 final FileOutputStream fstr = new FileOutputStream(publicZipFile);
6105 final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 final ZipFile privateZip = new ZipFile(newPackage.mPath);
6107
6108 // Copy manifest, resources.arsc and res directory to public zip
6109
6110 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
6111 while (privateZipEntries.hasMoreElements()) {
6112 final ZipEntry zipEntry = privateZipEntries.nextElement();
6113 final String zipEntryName = zipEntry.getName();
6114 if ("AndroidManifest.xml".equals(zipEntryName)
6115 || "resources.arsc".equals(zipEntryName)
6116 || zipEntryName.startsWith("res/")) {
6117 try {
6118 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
6119 } catch (IOException e) {
6120 try {
6121 publicZipOutStream.close();
6122 throw e;
6123 } finally {
6124 publicZipFile.delete();
6125 }
6126 }
6127 }
6128 }
6129
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07006130 publicZipOutStream.finish();
6131 publicZipOutStream.flush();
6132 FileUtils.sync(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006133 publicZipOutStream.close();
6134 FileUtils.setPermissions(
6135 publicZipFile.getAbsolutePath(),
6136 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
6137 -1, -1);
6138 }
6139
6140 private static void copyZipEntry(ZipEntry zipEntry,
6141 ZipFile inZipFile,
6142 ZipOutputStream outZipStream) throws IOException {
6143 byte[] buffer = new byte[4096];
6144 int num;
6145
6146 ZipEntry newEntry;
6147 if (zipEntry.getMethod() == ZipEntry.STORED) {
6148 // Preserve the STORED method of the input entry.
6149 newEntry = new ZipEntry(zipEntry);
6150 } else {
6151 // Create a new entry so that the compressed len is recomputed.
6152 newEntry = new ZipEntry(zipEntry.getName());
6153 }
6154 outZipStream.putNextEntry(newEntry);
6155
6156 InputStream data = inZipFile.getInputStream(zipEntry);
6157 while ((num = data.read(buffer)) > 0) {
6158 outZipStream.write(buffer, 0, num);
6159 }
6160 outZipStream.flush();
6161 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 private void deleteTempPackageFiles() {
6164 FilenameFilter filter = new FilenameFilter() {
6165 public boolean accept(File dir, String name) {
6166 return name.startsWith("vmdl") && name.endsWith(".tmp");
6167 }
6168 };
6169 String tmpFilesList[] = mAppInstallDir.list(filter);
6170 if(tmpFilesList == null) {
6171 return;
6172 }
6173 for(int i = 0; i < tmpFilesList.length; i++) {
6174 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
6175 tmpFile.delete();
6176 }
6177 }
6178
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006179 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 File tmpPackageFile;
6181 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006182 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006184 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006185 return null;
6186 }
6187 try {
6188 FileUtils.setPermissions(
6189 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
6190 -1, -1);
6191 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006192 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 return null;
6194 }
6195 return tmpPackageFile;
6196 }
6197
6198 public void deletePackage(final String packageName,
6199 final IPackageDeleteObserver observer,
6200 final int flags) {
6201 mContext.enforceCallingOrSelfPermission(
6202 android.Manifest.permission.DELETE_PACKAGES, null);
6203 // Queue up an async operation since the package deletion may take a little while.
6204 mHandler.post(new Runnable() {
6205 public void run() {
6206 mHandler.removeCallbacks(this);
6207 final boolean succeded = deletePackageX(packageName, true, true, flags);
6208 if (observer != null) {
6209 try {
6210 observer.packageDeleted(succeded);
6211 } catch (RemoteException e) {
6212 Log.i(TAG, "Observer no longer exists.");
6213 } //end catch
6214 } //end if
6215 } //end run
6216 });
6217 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 /**
6220 * This method is an internal method that could be get invoked either
6221 * to delete an installed package or to clean up a failed installation.
6222 * After deleting an installed package, a broadcast is sent to notify any
6223 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006224 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006225 * installation wouldn't have sent the initial broadcast either
6226 * The key steps in deleting a package are
6227 * deleting the package information in internal structures like mPackages,
6228 * deleting the packages base directories through installd
6229 * updating mSettings to reflect current status
6230 * persisting settings for later use
6231 * sending a broadcast if necessary
6232 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 private boolean deletePackageX(String packageName, boolean sendBroadCast,
6234 boolean deleteCodeAndResources, int flags) {
6235 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07006236 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006238 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
6239 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
6240 try {
6241 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006242 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006243 return false;
6244 }
6245 } catch (RemoteException e) {
6246 }
6247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 synchronized (mInstallLock) {
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006249 res = deletePackageLI(packageName, deleteCodeAndResources,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006250 flags | REMOVE_CHATTY, info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07006254 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006255 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
Romain Guy96f43572009-03-24 20:27:49 -07006256
6257 // If the removed package was a system update, the old system packaged
6258 // was re-enabled; we need to broadcast this information
6259 if (systemUpdate) {
6260 Bundle extras = new Bundle(1);
6261 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
6262 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6263
Dianne Hackborne7f97212011-02-24 14:40:20 -08006264 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
6265 extras, null, null);
6266 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
6267 extras, null, null);
6268 sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
6269 null, packageName, null);
Romain Guy96f43572009-03-24 20:27:49 -07006270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 }
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006272 // Force a gc here.
6273 Runtime.getRuntime().gc();
6274 // Delete the resources here after sending the broadcast to let
6275 // other processes clean up before deleting resources.
6276 if (info.args != null) {
6277 synchronized (mInstallLock) {
6278 info.args.doPostDeleteLI(deleteCodeAndResources);
6279 }
6280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006281 return res;
6282 }
6283
6284 static class PackageRemovedInfo {
6285 String removedPackage;
6286 int uid = -1;
6287 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07006288 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006289 // Clean up resources deleted packages.
6290 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07006291
Suchi Amalapurapudeb693702010-04-14 19:17:14 -07006292 void sendBroadcast(boolean fullRemove, boolean replacing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 Bundle extras = new Bundle(1);
6294 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
6295 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
6296 if (replacing) {
6297 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6298 }
6299 if (removedPackage != null) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08006300 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
6301 extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 }
6303 if (removedUid >= 0) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08006304 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006305 }
6306 }
6307 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006309 /*
6310 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
6311 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006312 * 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 -08006313 * delete a partially installed application.
6314 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006315 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006316 int flags, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006317 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006318 if (outInfo != null) {
6319 outInfo.removedPackage = packageName;
6320 }
Dianne Hackborn399cccb2010-04-13 22:57:49 -07006321 removePackageLI(p, (flags&REMOVE_CHATTY) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 // Retrieve object to delete permissions for shared user later on
6323 PackageSetting deletedPs;
6324 synchronized (mPackages) {
6325 deletedPs = mSettings.mPackages.get(packageName);
6326 }
6327 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6328 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006329 int retCode = mInstaller.remove(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006331 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 + packageName + ", retcode=" + retCode);
6333 // we don't consider this to be a failure of the core package deletion
6334 }
6335 } else {
Kenny Root85387d72010-08-26 10:13:11 -07006336 // for simulator
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 PackageParser.Package pkg = mPackages.get(packageName);
6338 File dataDir = new File(pkg.applicationInfo.dataDir);
6339 dataDir.delete();
6340 }
Dianne Hackbornfb1f1032010-07-29 13:57:56 -07006341 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 }
6343 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006344 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006345 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6346 if (outInfo != null) {
6347 outInfo.removedUid = mSettings.removePackageLP(packageName);
6348 }
6349 if (deletedPs != null) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07006350 updatePermissionsLP(deletedPs.name, null, false, false, false);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006351 if (deletedPs.sharedUser != null) {
6352 // remove permissions associated with package
6353 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
6354 }
6355 }
6356 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006357 // remove from preferred activities.
6358 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
6359 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
6360 if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
6361 removed.add(pa);
6362 }
6363 }
6364 for (PreferredActivity pa : removed) {
6365 mSettings.mPreferredActivities.removeFilter(pa);
6366 }
6367 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006368 if (writeSettings) {
6369 // Save settings now
6370 mSettings.writeLP();
6371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 }
6373 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 /*
6376 * Tries to delete system package.
6377 */
6378 private boolean deleteSystemPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006379 int flags, PackageRemovedInfo outInfo, boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 ApplicationInfo applicationInfo = p.applicationInfo;
6381 //applicable for non-partially installed applications only
6382 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006383 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 return false;
6385 }
6386 PackageSetting ps = null;
6387 // Confirm if the system package has been updated
6388 // An updated system app can be deleted. This will also have to restore
6389 // the system pkg from system partition
6390 synchronized (mPackages) {
6391 ps = mSettings.getDisabledSystemPkg(p.packageName);
6392 }
6393 if (ps == null) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006394 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006395 return false;
6396 } else {
6397 Log.i(TAG, "Deleting system pkg from data partition");
6398 }
6399 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07006400 outInfo.isRemovedPackageSystemUpdate = true;
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006401 if (ps.versionCode < p.mVersionCode) {
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006402 // Delete data for downgrades
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006403 flags &= ~PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006404 } else {
6405 // Preserve data by setting flag
Kenny Root7c1bd7f2010-09-01 13:44:11 -07006406 flags |= PackageManager.DONT_DELETE_DATA;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006407 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08006408 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006409 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 if (!ret) {
6411 return false;
6412 }
6413 synchronized (mPackages) {
6414 // Reinstate the old system package
6415 mSettings.enableSystemPackageLP(p.packageName);
Kenny Root8f7cc022010-09-12 09:04:56 -07006416 // Remove any native libraries from the upgraded package.
6417 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006418 }
6419 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006420 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006421 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Dianne Hackborn78d6883692010-10-07 01:12:46 -07006422 SCAN_MONITOR | SCAN_NO_PATHS, 0);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006425 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 return false;
6427 }
6428 synchronized (mPackages) {
Dianne Hackborn92cfa102010-04-28 11:00:44 -07006429 updatePermissionsLP(newPkg.packageName, newPkg, true, true, false);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006430 if (writeSettings) {
6431 mSettings.writeLP();
6432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 }
6434 return true;
6435 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006437 private boolean deleteInstalledPackageLI(PackageParser.Package p,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006438 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6439 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 ApplicationInfo applicationInfo = p.applicationInfo;
6441 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006442 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 return false;
6444 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006445 if (outInfo != null) {
6446 outInfo.uid = applicationInfo.uid;
6447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448
6449 // Delete package data from internal structures and also remove data if flag is set
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006450 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451
6452 // Delete application code and resources
6453 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006454 // TODO can pick up from PackageSettings as well
Kenny Root85387d72010-08-26 10:13:11 -07006455 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
6456 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
6457 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
6458 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006459 }
6460 return true;
6461 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 /*
6464 * This method handles package deletion in general
6465 */
6466 private boolean deletePackageLI(String packageName,
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006467 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo,
6468 boolean writeSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006469 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006470 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 return false;
6472 }
6473 PackageParser.Package p;
6474 boolean dataOnly = false;
6475 synchronized (mPackages) {
6476 p = mPackages.get(packageName);
6477 if (p == null) {
6478 //this retrieves partially installed apps
6479 dataOnly = true;
6480 PackageSetting ps = mSettings.mPackages.get(packageName);
6481 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006482 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 return false;
6484 }
6485 p = ps.pkg;
6486 }
6487 }
6488 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006489 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 return false;
6491 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 if (dataOnly) {
6494 // Delete application data first
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006495 removePackageDataLI(p, outInfo, flags, writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 return true;
6497 }
6498 // At this point the package should have ApplicationInfo associated with it
6499 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006500 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 return false;
6502 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006503 boolean ret = false;
Kenny Root85387d72010-08-26 10:13:11 -07006504 if (isSystemApp(p)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 Log.i(TAG, "Removing system package:"+p.packageName);
6506 // When an updated system application is deleted we delete the existing resources as well and
6507 // fall back to existing code in system partition
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006508 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006509 } else {
6510 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006511 // Kill application pre-emptively especially for apps on sd.
6512 killApplication(packageName, p.applicationInfo.uid);
Dianne Hackborn3aeee332010-10-02 18:56:33 -07006513 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
6514 writeSettings);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006516 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 public void clearApplicationUserData(final String packageName,
6520 final IPackageDataObserver observer) {
6521 mContext.enforceCallingOrSelfPermission(
6522 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
6523 // Queue up an async operation since the package deletion may take a little while.
6524 mHandler.post(new Runnable() {
6525 public void run() {
6526 mHandler.removeCallbacks(this);
6527 final boolean succeeded;
6528 synchronized (mInstallLock) {
6529 succeeded = clearApplicationUserDataLI(packageName);
6530 }
6531 if (succeeded) {
6532 // invoke DeviceStorageMonitor's update method to clear any notifications
6533 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
6534 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
6535 if (dsm != null) {
6536 dsm.updateMemory();
6537 }
6538 }
6539 if(observer != null) {
6540 try {
6541 observer.onRemoveCompleted(packageName, succeeded);
6542 } catch (RemoteException e) {
6543 Log.i(TAG, "Observer no longer exists.");
6544 }
6545 } //end if observer
6546 } //end run
6547 });
6548 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006550 private boolean clearApplicationUserDataLI(String packageName) {
6551 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006552 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 return false;
6554 }
6555 PackageParser.Package p;
6556 boolean dataOnly = false;
6557 synchronized (mPackages) {
6558 p = mPackages.get(packageName);
6559 if(p == null) {
6560 dataOnly = true;
6561 PackageSetting ps = mSettings.mPackages.get(packageName);
6562 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006563 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 return false;
6565 }
6566 p = ps.pkg;
6567 }
6568 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006569
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08006570 if (!dataOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006571 //need to check this only for fully installed applications
6572 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006573 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 return false;
6575 }
6576 final ApplicationInfo applicationInfo = p.applicationInfo;
6577 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006578 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006579 return false;
6580 }
6581 }
6582 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006583 int retCode = mInstaller.clearUserData(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006584 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006585 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006586 + packageName);
6587 return false;
6588 }
6589 }
6590 return true;
6591 }
6592
6593 public void deleteApplicationCacheFiles(final String packageName,
6594 final IPackageDataObserver observer) {
6595 mContext.enforceCallingOrSelfPermission(
6596 android.Manifest.permission.DELETE_CACHE_FILES, null);
6597 // Queue up an async operation since the package deletion may take a little while.
6598 mHandler.post(new Runnable() {
6599 public void run() {
6600 mHandler.removeCallbacks(this);
6601 final boolean succeded;
6602 synchronized (mInstallLock) {
6603 succeded = deleteApplicationCacheFilesLI(packageName);
6604 }
6605 if(observer != null) {
6606 try {
6607 observer.onRemoveCompleted(packageName, succeded);
6608 } catch (RemoteException e) {
6609 Log.i(TAG, "Observer no longer exists.");
6610 }
6611 } //end if observer
6612 } //end run
6613 });
6614 }
6615
6616 private boolean deleteApplicationCacheFilesLI(String packageName) {
6617 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006618 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 return false;
6620 }
6621 PackageParser.Package p;
6622 synchronized (mPackages) {
6623 p = mPackages.get(packageName);
6624 }
6625 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006626 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006627 return false;
6628 }
6629 final ApplicationInfo applicationInfo = p.applicationInfo;
6630 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006631 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006632 return false;
6633 }
6634 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006635 int retCode = mInstaller.deleteCacheFiles(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006637 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006638 + packageName);
6639 return false;
6640 }
6641 }
6642 return true;
6643 }
6644
6645 public void getPackageSizeInfo(final String packageName,
6646 final IPackageStatsObserver observer) {
6647 mContext.enforceCallingOrSelfPermission(
6648 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6649 // Queue up an async operation since the package deletion may take a little while.
6650 mHandler.post(new Runnable() {
6651 public void run() {
6652 mHandler.removeCallbacks(this);
Kenny Root366949c2011-01-14 17:18:14 -08006653 PackageStats stats = new PackageStats(packageName);
6654
6655 final boolean success;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 synchronized (mInstallLock) {
Kenny Root366949c2011-01-14 17:18:14 -08006657 success = getPackageSizeInfoLI(packageName, stats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 }
Kenny Root366949c2011-01-14 17:18:14 -08006659
6660 Message msg = mHandler.obtainMessage(INIT_COPY);
6661 msg.obj = new MeasureParams(stats, success, observer);
6662 mHandler.sendMessage(msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 } //end run
6664 });
6665 }
6666
6667 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6668 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006669 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670 return false;
6671 }
6672 PackageParser.Package p;
6673 boolean dataOnly = false;
6674 synchronized (mPackages) {
6675 p = mPackages.get(packageName);
6676 if(p == null) {
6677 dataOnly = true;
6678 PackageSetting ps = mSettings.mPackages.get(packageName);
6679 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006680 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006681 return false;
6682 }
6683 p = ps.pkg;
6684 }
6685 }
6686 String publicSrcDir = null;
6687 if(!dataOnly) {
6688 final ApplicationInfo applicationInfo = p.applicationInfo;
6689 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006690 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006691 return false;
6692 }
6693 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6694 }
6695 if (mInstaller != null) {
Kenny Root35ab3ad2011-02-02 16:42:14 -08006696 int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 if (res < 0) {
6698 return false;
6699 } else {
6700 return true;
6701 }
6702 }
6703 return true;
6704 }
6705
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 public void addPackageToPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006708 Slog.w(TAG, "addPackageToPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006709 }
6710
6711 public void removePackageFromPreferred(String packageName) {
Dianne Hackborn8377fc02010-06-07 15:54:58 -07006712 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006713 }
6714
6715 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006716 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006717 }
6718
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006719 int getUidTargetSdkVersionLockedLP(int uid) {
6720 Object obj = mSettings.getUserIdLP(uid);
6721 if (obj instanceof SharedUserSetting) {
6722 SharedUserSetting sus = (SharedUserSetting)obj;
6723 final int N = sus.packages.size();
6724 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
6725 Iterator<PackageSetting> it = sus.packages.iterator();
6726 int i=0;
6727 while (it.hasNext()) {
6728 PackageSetting ps = it.next();
6729 if (ps.pkg != null) {
6730 int v = ps.pkg.applicationInfo.targetSdkVersion;
6731 if (v < vers) vers = v;
6732 }
6733 }
6734 return vers;
6735 } else if (obj instanceof PackageSetting) {
6736 PackageSetting ps = (PackageSetting)obj;
6737 if (ps.pkg != null) {
6738 return ps.pkg.applicationInfo.targetSdkVersion;
6739 }
6740 }
6741 return Build.VERSION_CODES.CUR_DEVELOPMENT;
6742 }
6743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 public void addPreferredActivity(IntentFilter filter, int match,
6745 ComponentName[] set, ComponentName activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006747 if (mContext.checkCallingOrSelfPermission(
6748 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6749 != PackageManager.PERMISSION_GRANTED) {
6750 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6751 < Build.VERSION_CODES.FROYO) {
6752 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
6753 + Binder.getCallingUid());
6754 return;
6755 }
6756 mContext.enforceCallingOrSelfPermission(
6757 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6758 }
6759
6760 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006761 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6762 mSettings.mPreferredActivities.addFilter(
6763 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006764 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 }
6766 }
6767
Satish Sampath8dbe6122009-06-02 23:35:54 +01006768 public void replacePreferredActivity(IntentFilter filter, int match,
6769 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01006770 if (filter.countActions() != 1) {
6771 throw new IllegalArgumentException(
6772 "replacePreferredActivity expects filter to have only 1 action.");
6773 }
6774 if (filter.countCategories() != 1) {
6775 throw new IllegalArgumentException(
6776 "replacePreferredActivity expects filter to have only 1 category.");
6777 }
6778 if (filter.countDataAuthorities() != 0
6779 || filter.countDataPaths() != 0
6780 || filter.countDataSchemes() != 0
6781 || filter.countDataTypes() != 0) {
6782 throw new IllegalArgumentException(
6783 "replacePreferredActivity expects filter to have no data authorities, " +
6784 "paths, schemes or types.");
6785 }
6786 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006787 if (mContext.checkCallingOrSelfPermission(
6788 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6789 != PackageManager.PERMISSION_GRANTED) {
6790 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6791 < Build.VERSION_CODES.FROYO) {
6792 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
6793 + Binder.getCallingUid());
6794 return;
6795 }
6796 mContext.enforceCallingOrSelfPermission(
6797 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6798 }
6799
Satish Sampath8dbe6122009-06-02 23:35:54 +01006800 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6801 String action = filter.getAction(0);
6802 String category = filter.getCategory(0);
6803 while (it.hasNext()) {
6804 PreferredActivity pa = it.next();
6805 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6806 it.remove();
6807 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
6808 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6809 }
6810 }
6811 addPreferredActivity(filter, match, set, activity);
6812 }
6813 }
6814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 public void clearPackagePreferredActivities(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006817 int uid = Binder.getCallingUid();
6818 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006819 if (pkg == null || pkg.applicationInfo.uid != uid) {
6820 if (mContext.checkCallingOrSelfPermission(
6821 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6822 != PackageManager.PERMISSION_GRANTED) {
6823 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6824 < Build.VERSION_CODES.FROYO) {
6825 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
6826 + Binder.getCallingUid());
6827 return;
6828 }
6829 mContext.enforceCallingOrSelfPermission(
6830 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6831 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006832 }
6833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834 if (clearPackagePreferredActivitiesLP(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006835 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006836 }
6837 }
6838 }
6839
6840 boolean clearPackagePreferredActivitiesLP(String packageName) {
6841 boolean changed = false;
6842 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6843 while (it.hasNext()) {
6844 PreferredActivity pa = it.next();
6845 if (pa.mActivity.getPackageName().equals(packageName)) {
6846 it.remove();
6847 changed = true;
6848 }
6849 }
6850 return changed;
6851 }
6852
6853 public int getPreferredActivities(List<IntentFilter> outFilters,
6854 List<ComponentName> outActivities, String packageName) {
6855
6856 int num = 0;
6857 synchronized (mPackages) {
6858 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6859 while (it.hasNext()) {
6860 PreferredActivity pa = it.next();
6861 if (packageName == null
6862 || pa.mActivity.getPackageName().equals(packageName)) {
6863 if (outFilters != null) {
6864 outFilters.add(new IntentFilter(pa));
6865 }
6866 if (outActivities != null) {
6867 outActivities.add(pa.mActivity);
6868 }
6869 }
6870 }
6871 }
6872
6873 return num;
6874 }
6875
6876 public void setApplicationEnabledSetting(String appPackageName,
6877 int newState, int flags) {
6878 setEnabledSetting(appPackageName, null, newState, flags);
6879 }
6880
6881 public void setComponentEnabledSetting(ComponentName componentName,
6882 int newState, int flags) {
6883 setEnabledSetting(componentName.getPackageName(),
6884 componentName.getClassName(), newState, flags);
6885 }
6886
6887 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006888 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006889 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
6890 || newState == COMPONENT_ENABLED_STATE_ENABLED
6891 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
6892 throw new IllegalArgumentException("Invalid new component state: "
6893 + newState);
6894 }
6895 PackageSetting pkgSetting;
6896 final int uid = Binder.getCallingUid();
6897 final int permission = mContext.checkCallingPermission(
6898 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
6899 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006900 boolean sendNow = false;
6901 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006902 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006903 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006904 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006905 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006906 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006907 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006908 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006909 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006910 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 }
6912 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006913 "Unknown component: " + packageName
6914 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 }
6916 if (!allowedByPermission && (uid != pkgSetting.userId)) {
6917 throw new SecurityException(
6918 "Permission Denial: attempt to change component state from pid="
6919 + Binder.getCallingPid()
6920 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
6921 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006922 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006923 // We're dealing with an application/package level state change
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006924 if (pkgSetting.enabled == newState) {
6925 // Nothing to do
6926 return;
6927 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 pkgSetting.enabled = newState;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07006929 pkgSetting.pkg.mSetEnabled = newState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 } else {
6931 // We're dealing with a component level state change
6932 switch (newState) {
6933 case COMPONENT_ENABLED_STATE_ENABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006934 if (!pkgSetting.enableComponentLP(className)) {
6935 return;
6936 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006937 break;
6938 case COMPONENT_ENABLED_STATE_DISABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006939 if (!pkgSetting.disableComponentLP(className)) {
6940 return;
6941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006942 break;
6943 case COMPONENT_ENABLED_STATE_DEFAULT:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006944 if (!pkgSetting.restoreComponentLP(className)) {
6945 return;
6946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947 break;
6948 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006949 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006950 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 }
6952 }
6953 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006954 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006955 components = mPendingBroadcasts.get(packageName);
6956 boolean newPackage = components == null;
6957 if (newPackage) {
6958 components = new ArrayList<String>();
6959 }
6960 if (!components.contains(componentName)) {
6961 components.add(componentName);
6962 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006963 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6964 sendNow = true;
6965 // Purge entry from pending broadcast list if another one exists already
6966 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006967 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006968 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006969 if (newPackage) {
6970 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006971 }
6972 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6973 // Schedule a message
6974 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6975 }
6976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006977 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006979 long callingId = Binder.clearCallingIdentity();
6980 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006981 if (sendNow) {
6982 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006983 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 } finally {
6986 Binder.restoreCallingIdentity(callingId);
6987 }
6988 }
6989
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006990 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006991 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6992 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6993 + " components=" + componentNames);
6994 Bundle extras = new Bundle(4);
6995 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6996 String nameList[] = new String[componentNames.size()];
6997 componentNames.toArray(nameList);
6998 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006999 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
7000 extras.putInt(Intent.EXTRA_UID, packageUid);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007001 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null);
7002 }
7003
7004 public void setPackageStoppedState(String packageName, boolean stopped) {
7005 PackageSetting pkgSetting;
7006 final int uid = Binder.getCallingUid();
7007 final int permission = mContext.checkCallingOrSelfPermission(
7008 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
7009 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
7010 synchronized (mPackages) {
7011 pkgSetting = mSettings.mPackages.get(packageName);
7012 if (pkgSetting == null) {
7013 throw new IllegalArgumentException("Unknown package: " + packageName);
7014 }
7015 if (!allowedByPermission && (uid != pkgSetting.userId)) {
7016 throw new SecurityException(
7017 "Permission Denial: attempt to change stopped state from pid="
7018 + Binder.getCallingPid()
7019 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
7020 }
7021 if (DEBUG_STOPPED && stopped) {
7022 RuntimeException e = new RuntimeException("here");
7023 e.fillInStackTrace();
7024 Slog.i(TAG, "Stopping package " + packageName, e);
7025 }
7026 if (pkgSetting.stopped != stopped) {
7027 pkgSetting.stopped = stopped;
7028 pkgSetting.pkg.mSetStopped = stopped;
7029 if (pkgSetting.notLaunched) {
7030 if (pkgSetting.installerPackageName != null) {
7031 sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
7032 pkgSetting.installerPackageName, null,
7033 pkgSetting.name, null);
7034 }
7035 pkgSetting.notLaunched = false;
7036 }
7037 scheduleWriteStoppedPackagesLocked();
7038 }
7039 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07007040 }
7041
Jacek Surazski65e13172009-04-28 15:26:38 +02007042 public String getInstallerPackageName(String packageName) {
7043 synchronized (mPackages) {
7044 PackageSetting pkg = mSettings.mPackages.get(packageName);
7045 if (pkg == null) {
7046 throw new IllegalArgumentException("Unknown package: " + packageName);
7047 }
7048 return pkg.installerPackageName;
7049 }
7050 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007052 public int getApplicationEnabledSetting(String appPackageName) {
7053 synchronized (mPackages) {
7054 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
7055 if (pkg == null) {
7056 throw new IllegalArgumentException("Unknown package: " + appPackageName);
7057 }
7058 return pkg.enabled;
7059 }
7060 }
7061
7062 public int getComponentEnabledSetting(ComponentName componentName) {
7063 synchronized (mPackages) {
7064 final String packageNameStr = componentName.getPackageName();
7065 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
7066 if (pkg == null) {
7067 throw new IllegalArgumentException("Unknown component: " + componentName);
7068 }
7069 final String classNameStr = componentName.getClassName();
7070 return pkg.currentEnabledStateLP(classNameStr);
7071 }
7072 }
7073
7074 public void enterSafeMode() {
7075 if (!mSystemReady) {
7076 mSafeMode = true;
7077 }
7078 }
7079
7080 public void systemReady() {
7081 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007082
7083 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007084 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007085 mContext.getContentResolver(),
7086 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007087 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007088 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07007089 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07007090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 }
7092
7093 public boolean isSafeMode() {
7094 return mSafeMode;
7095 }
7096
7097 public boolean hasSystemUidErrors() {
7098 return mHasSystemUidErrors;
7099 }
7100
7101 static String arrayToString(int[] array) {
7102 StringBuffer buf = new StringBuffer(128);
7103 buf.append('[');
7104 if (array != null) {
7105 for (int i=0; i<array.length; i++) {
7106 if (i > 0) buf.append(", ");
7107 buf.append(array[i]);
7108 }
7109 }
7110 buf.append(']');
7111 return buf.toString();
7112 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 @Override
7115 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7116 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
7117 != PackageManager.PERMISSION_GRANTED) {
7118 pw.println("Permission Denial: can't dump ActivityManager from from pid="
7119 + Binder.getCallingPid()
7120 + ", uid=" + Binder.getCallingUid()
7121 + " without permission "
7122 + android.Manifest.permission.DUMP);
7123 return;
7124 }
7125
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007126 boolean dumpStar = true;
7127 boolean dumpLibs = false;
7128 boolean dumpFeatures = false;
7129 boolean dumpResolvers = false;
7130 boolean dumpPermissions = false;
7131 boolean dumpPackages = false;
7132 boolean dumpSharedUsers = false;
7133 boolean dumpMessages = false;
7134 boolean dumpProviders = false;
7135
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007136 String packageName = null;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007137 boolean showFilters = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007138
7139 int opti = 0;
7140 while (opti < args.length) {
7141 String opt = args[opti];
7142 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
7143 break;
7144 }
7145 opti++;
7146 if ("-a".equals(opt)) {
7147 // Right now we only know how to print all.
7148 } else if ("-h".equals(opt)) {
7149 pw.println("Package manager dump options:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007150 pw.println(" [-h] [-f] [cmd] ...");
7151 pw.println(" -f: print details of intent filters");
7152 pw.println(" -h: print this help");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007153 pw.println(" cmd may be one of:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007154 pw.println(" l[ibraries]: list known shared libraries");
7155 pw.println(" f[ibraries]: list device features");
7156 pw.println(" r[esolvers]: dump intent resolvers");
7157 pw.println(" perm[issions]: dump permissions");
7158 pw.println(" prov[iders]: dump content providers");
7159 pw.println(" p[ackages]: dump installed packages");
7160 pw.println(" s[hared-users]: dump shared user IDs");
7161 pw.println(" m[essages]: print collected runtime messages");
7162 pw.println(" <package.name>: info about given package");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007163 return;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007164 } else if ("-f".equals(opt)) {
7165 showFilters = true;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007166 } else {
7167 pw.println("Unknown argument: " + opt + "; use -h for help");
7168 }
7169 }
7170
7171 // Is the caller requesting to dump a particular piece of data?
7172 if (opti < args.length) {
7173 String cmd = args[opti];
7174 opti++;
7175 // Is this a package name?
7176 if ("android".equals(cmd) || cmd.contains(".")) {
7177 packageName = cmd;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007178 } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
7179 dumpStar = false;
7180 dumpLibs = true;
7181 } else if ("f".equals(cmd) || "features".equals(cmd)) {
7182 dumpStar = false;
7183 dumpFeatures = true;
7184 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) {
7185 dumpStar = false;
7186 dumpResolvers = true;
7187 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
7188 dumpStar = false;
7189 dumpPermissions = true;
7190 } else if ("p".equals(cmd) || "packages".equals(cmd)) {
7191 dumpStar = false;
7192 dumpPackages = true;
7193 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) {
7194 dumpStar = false;
7195 dumpSharedUsers = true;
7196 } else if ("prov".equals(cmd) || "providers".equals(cmd)) {
7197 dumpStar = false;
7198 dumpProviders = true;
7199 } else if ("m".equals(cmd) || "messages".equals(cmd)) {
7200 dumpStar = false;
7201 dumpMessages = true;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007202 }
7203 }
7204
7205 boolean printedTitle = false;
7206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 synchronized (mPackages) {
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007208 if ((dumpStar || dumpLibs) && packageName == null) {
7209 if (printedTitle) pw.println(" ");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007210 printedTitle = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007211 pw.println("Libraries:");
7212 Iterator<String> it = mSharedLibraries.keySet().iterator();
7213 while (it.hasNext()) {
7214 String name = it.next();
7215 pw.print(" ");
7216 pw.print(name);
7217 pw.print(" -> ");
7218 pw.println(mSharedLibraries.get(name));
7219 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007220 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007221
7222 if ((dumpStar || dumpFeatures) && packageName == null) {
7223 if (printedTitle) pw.println(" ");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007224 printedTitle = true;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007225 pw.println("Features:");
7226 Iterator<String> it = mAvailableFeatures.keySet().iterator();
7227 while (it.hasNext()) {
7228 String name = it.next();
7229 pw.print(" ");
7230 pw.println(name);
7231 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007232 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007233
7234 if (dumpStar || dumpResolvers) {
7235 if (mActivities.dump(pw, printedTitle
7236 ? "\nActivity Resolver Table:" : "Activity Resolver Table:",
7237 " ", packageName, showFilters)) {
7238 printedTitle = true;
7239 }
7240 if (mReceivers.dump(pw, printedTitle
7241 ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:",
7242 " ", packageName, showFilters)) {
7243 printedTitle = true;
7244 }
7245 if (mServices.dump(pw, printedTitle
7246 ? "\nService Resolver Table:" : "Service Resolver Table:",
7247 " ", packageName, showFilters)) {
7248 printedTitle = true;
7249 }
7250 if (mSettings.mPreferredActivities.dump(pw, printedTitle
7251 ? "\nPreferred Activities:" : "Preferred Activities:",
7252 " ", packageName, showFilters)) {
7253 printedTitle = true;
7254 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007255 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007256
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007257 boolean printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007258 if (dumpStar || dumpPermissions) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007260 if (packageName != null && !packageName.equals(p.sourcePackage)) {
7261 continue;
7262 }
7263 if (!printedSomething) {
7264 if (printedTitle) pw.println(" ");
7265 pw.println("Permissions:");
7266 printedSomething = true;
7267 printedTitle = true;
7268 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007269 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
7270 pw.print(Integer.toHexString(System.identityHashCode(p)));
7271 pw.println("):");
7272 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
7273 pw.print(" uid="); pw.print(p.uid);
7274 pw.print(" gids="); pw.print(arrayToString(p.gids));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007275 pw.print(" type="); pw.print(p.type);
7276 pw.print(" prot="); pw.println(p.protectionLevel);
7277 if (p.packageSetting != null) {
7278 pw.print(" packageSetting="); pw.println(p.packageSetting);
7279 }
7280 if (p.perm != null) {
7281 pw.print(" perm="); pw.println(p.perm);
7282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 }
7284 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007285
7286 if (dumpStar || dumpProviders) {
7287 printedSomething = false;
7288 for (PackageParser.Provider p : mProviders.values()) {
7289 if (packageName != null && !packageName.equals(p.info.packageName)) {
7290 continue;
7291 }
7292 if (!printedSomething) {
7293 if (printedTitle) pw.println(" ");
7294 pw.println("Registered ContentProviders:");
7295 printedSomething = true;
7296 printedTitle = true;
7297 }
7298 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
7299 pw.println(p.toString());
7300 }
7301 }
7302
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007303 printedSomething = false;
7304 SharedUserSetting packageSharedUser = null;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007305 if (dumpStar || dumpPackages) {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007306 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
7307 Date date = new Date();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007308 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007309 if (packageName != null && !packageName.equals(ps.realName)
7310 && !packageName.equals(ps.name)) {
7311 continue;
7312 }
7313 if (!printedSomething) {
7314 if (printedTitle) pw.println(" ");
7315 pw.println("Packages:");
7316 printedSomething = true;
7317 printedTitle = true;
7318 }
7319 packageSharedUser = ps.sharedUser;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007320 pw.print(" Package [");
7321 pw.print(ps.realName != null ? ps.realName : ps.name);
7322 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007323 pw.print(Integer.toHexString(System.identityHashCode(ps)));
7324 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007325 if (ps.realName != null) {
7326 pw.print(" compat name="); pw.println(ps.name);
7327 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007328 pw.print(" userId="); pw.print(ps.userId);
7329 pw.print(" gids="); pw.println(arrayToString(ps.gids));
7330 pw.print(" sharedUser="); pw.println(ps.sharedUser);
7331 pw.print(" pkg="); pw.println(ps.pkg);
7332 pw.print(" codePath="); pw.println(ps.codePathString);
7333 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
Kenny Root85387d72010-08-26 10:13:11 -07007334 pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
Kenny Root1174f712010-10-22 10:07:11 -07007335 pw.print(" versionCode="); pw.println(ps.versionCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 if (ps.pkg != null) {
Kenny Root1174f712010-10-22 10:07:11 -07007337 pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007338 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007339 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Kenny Root85387d72010-08-26 10:13:11 -07007340 if (ps.pkg.mOperationPending) {
7341 pw.println(" mOperationPending=true");
7342 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007343 pw.print(" supportsScreens=[");
7344 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007345 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007346 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
7347 if (!first) pw.print(", ");
7348 first = false;
7349 pw.print("small");
7350 }
7351 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007352 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007353 if (!first) pw.print(", ");
7354 first = false;
7355 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007356 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007357 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007358 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007359 if (!first) pw.print(", ");
7360 first = false;
7361 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007362 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007363 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007364 ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007365 if (!first) pw.print(", ");
7366 first = false;
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07007367 pw.print("xlarge");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07007368 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007369 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007370 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007371 if (!first) pw.print(", ");
7372 first = false;
7373 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007374 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007375 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007376 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
7377 if (!first) pw.print(", ");
7378 first = false;
7379 pw.print("anyDensity");
7380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007381 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007382 pw.println("]");
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007383 pw.print(" timeStamp=");
7384 date.setTime(ps.timeStamp); pw.println(sdf.format(date));
7385 pw.print(" firstInstallTime=");
7386 date.setTime(ps.firstInstallTime); pw.println(sdf.format(date));
7387 pw.print(" lastUpdateTime=");
7388 date.setTime(ps.lastUpdateTime); pw.println(sdf.format(date));
Dianne Hackborne7f97212011-02-24 14:40:20 -08007389 if (ps.installerPackageName != null) {
7390 pw.print(" installerPackageName="); pw.println(ps.installerPackageName);
7391 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007392 pw.print(" signatures="); pw.println(ps.signatures);
7393 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007394 pw.print(" haveGids="); pw.println(ps.haveGids);
7395 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007396 pw.print(" installStatus="); pw.print(ps.installStatus);
Dianne Hackborne7f97212011-02-24 14:40:20 -08007397 pw.print(" stopped="); pw.print(ps.stopped);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007398 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007399 if (ps.disabledComponents.size() > 0) {
7400 pw.println(" disabledComponents:");
7401 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007402 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 }
7404 }
7405 if (ps.enabledComponents.size() > 0) {
7406 pw.println(" enabledComponents:");
7407 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007408 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 }
7410 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007411 if (ps.grantedPermissions.size() > 0) {
7412 pw.println(" grantedPermissions:");
7413 for (String s : ps.grantedPermissions) {
7414 pw.print(" "); pw.println(s);
7415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 }
7418 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007419 printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007420 if (dumpStar || dumpPackages) {
7421 if (mSettings.mRenamedPackages.size() > 0) {
7422 for (HashMap.Entry<String, String> e
7423 : mSettings.mRenamedPackages.entrySet()) {
7424 if (packageName != null && !packageName.equals(e.getKey())
7425 && !packageName.equals(e.getValue())) {
7426 continue;
7427 }
7428 if (!printedSomething) {
7429 if (printedTitle) pw.println(" ");
7430 pw.println("Renamed packages:");
7431 printedSomething = true;
7432 printedTitle = true;
7433 }
7434 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
7435 pw.println(e.getValue());
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007436 }
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007437 }
7438 printedSomething = false;
7439 if (mSettings.mDisabledSysPackages.size() > 0) {
7440 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
7441 if (packageName != null && !packageName.equals(ps.realName)
7442 && !packageName.equals(ps.name)) {
7443 continue;
7444 }
7445 if (!printedSomething) {
7446 if (printedTitle) pw.println(" ");
7447 pw.println("Hidden system packages:");
7448 printedSomething = true;
7449 printedTitle = true;
7450 }
7451 pw.print(" Package [");
7452 pw.print(ps.realName != null ? ps.realName : ps.name);
7453 pw.print("] (");
7454 pw.print(Integer.toHexString(System.identityHashCode(ps)));
7455 pw.println("):");
7456 if (ps.realName != null) {
7457 pw.print(" compat name="); pw.println(ps.name);
7458 }
7459 pw.print(" userId="); pw.println(ps.userId);
7460 pw.print(" sharedUser="); pw.println(ps.sharedUser);
7461 pw.print(" codePath="); pw.println(ps.codePathString);
7462 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007463 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007464 }
7465 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007466 printedSomething = false;
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007467 if (dumpStar || dumpSharedUsers) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007469 if (packageName != null && su != packageSharedUser) {
7470 continue;
7471 }
7472 if (!printedSomething) {
7473 if (printedTitle) pw.println(" ");
7474 pw.println("Shared users:");
7475 printedSomething = true;
7476 printedTitle = true;
7477 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007478 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
7479 pw.print(Integer.toHexString(System.identityHashCode(su)));
7480 pw.println("):");
7481 pw.print(" userId="); pw.print(su.userId);
7482 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 pw.println(" grantedPermissions:");
7484 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007485 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 }
7488 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007489
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007490 if ((dumpStar || dumpMessages) && packageName == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007491 if (printedTitle) pw.println(" ");
7492 printedTitle = true;
7493 pw.println("Settings parse messages:");
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007494 pw.print(mSettings.mReadMessages.toString());
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007495
7496 pw.println(" ");
7497 pw.println("Package warning messages:");
7498 File fname = getSettingsProblemFile();
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007499 FileInputStream in = null;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007500 try {
7501 in = new FileInputStream(fname);
7502 int avail = in.available();
7503 byte[] data = new byte[avail];
7504 in.read(data);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07007505 pw.print(new String(data));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007506 } catch (FileNotFoundException e) {
7507 } catch (IOException e) {
Brad Fitzpatrick6689ac82010-11-15 16:26:04 -08007508 } finally {
7509 if (in != null) {
7510 try {
7511 in.close();
7512 } catch (IOException e) {
7513 }
7514 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007515 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 }
7518 }
7519
7520 static final class BasePermission {
7521 final static int TYPE_NORMAL = 0;
7522 final static int TYPE_BUILTIN = 1;
7523 final static int TYPE_DYNAMIC = 2;
7524
7525 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007526 String sourcePackage;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007527 PackageSettingBase packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007528 final int type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007529 int protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007530 PackageParser.Permission perm;
7531 PermissionInfo pendingInfo;
7532 int uid;
7533 int[] gids;
7534
7535 BasePermission(String _name, String _sourcePackage, int _type) {
7536 name = _name;
7537 sourcePackage = _sourcePackage;
7538 type = _type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007539 // Default to most conservative protection level.
7540 protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
7541 }
7542
7543 public String toString() {
7544 return "BasePermission{"
7545 + Integer.toHexString(System.identityHashCode(this))
7546 + " " + name + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 }
7548 }
7549
7550 static class PackageSignatures {
7551 private Signature[] mSignatures;
7552
Kenny Root291e78c2011-01-13 14:53:17 -08007553 PackageSignatures(PackageSignatures orig) {
Kenny Rootbd392c52011-01-14 10:34:56 -08007554 if (orig != null && orig.mSignatures != null) {
7555 mSignatures = orig.mSignatures.clone();
7556 }
Kenny Root291e78c2011-01-13 14:53:17 -08007557 }
7558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 PackageSignatures(Signature[] sigs) {
7560 assignSignatures(sigs);
7561 }
7562
7563 PackageSignatures() {
7564 }
7565
7566 void writeXml(XmlSerializer serializer, String tagName,
7567 ArrayList<Signature> pastSignatures) throws IOException {
7568 if (mSignatures == null) {
7569 return;
7570 }
7571 serializer.startTag(null, tagName);
7572 serializer.attribute(null, "count",
7573 Integer.toString(mSignatures.length));
7574 for (int i=0; i<mSignatures.length; i++) {
7575 serializer.startTag(null, "cert");
7576 final Signature sig = mSignatures[i];
7577 final int sigHash = sig.hashCode();
7578 final int numPast = pastSignatures.size();
7579 int j;
7580 for (j=0; j<numPast; j++) {
7581 Signature pastSig = pastSignatures.get(j);
7582 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
7583 serializer.attribute(null, "index", Integer.toString(j));
7584 break;
7585 }
7586 }
7587 if (j >= numPast) {
7588 pastSignatures.add(sig);
7589 serializer.attribute(null, "index", Integer.toString(numPast));
7590 serializer.attribute(null, "key", sig.toCharsString());
7591 }
7592 serializer.endTag(null, "cert");
7593 }
7594 serializer.endTag(null, tagName);
7595 }
7596
7597 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
7598 throws IOException, XmlPullParserException {
7599 String countStr = parser.getAttributeValue(null, "count");
7600 if (countStr == null) {
7601 reportSettingsProblem(Log.WARN,
7602 "Error in package manager settings: <signatures> has"
7603 + " no count at " + parser.getPositionDescription());
7604 XmlUtils.skipCurrentTag(parser);
7605 }
7606 final int count = Integer.parseInt(countStr);
7607 mSignatures = new Signature[count];
7608 int pos = 0;
7609
7610 int outerDepth = parser.getDepth();
7611 int type;
7612 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7613 && (type != XmlPullParser.END_TAG
7614 || parser.getDepth() > outerDepth)) {
7615 if (type == XmlPullParser.END_TAG
7616 || type == XmlPullParser.TEXT) {
7617 continue;
7618 }
7619
7620 String tagName = parser.getName();
7621 if (tagName.equals("cert")) {
7622 if (pos < count) {
7623 String index = parser.getAttributeValue(null, "index");
7624 if (index != null) {
7625 try {
7626 int idx = Integer.parseInt(index);
7627 String key = parser.getAttributeValue(null, "key");
7628 if (key == null) {
7629 if (idx >= 0 && idx < pastSignatures.size()) {
7630 Signature sig = pastSignatures.get(idx);
7631 if (sig != null) {
7632 mSignatures[pos] = pastSignatures.get(idx);
7633 pos++;
7634 } else {
7635 reportSettingsProblem(Log.WARN,
7636 "Error in package manager settings: <cert> "
7637 + "index " + index + " is not defined at "
7638 + parser.getPositionDescription());
7639 }
7640 } else {
7641 reportSettingsProblem(Log.WARN,
7642 "Error in package manager settings: <cert> "
7643 + "index " + index + " is out of bounds at "
7644 + parser.getPositionDescription());
7645 }
7646 } else {
7647 while (pastSignatures.size() <= idx) {
7648 pastSignatures.add(null);
7649 }
7650 Signature sig = new Signature(key);
7651 pastSignatures.set(idx, sig);
7652 mSignatures[pos] = sig;
7653 pos++;
7654 }
7655 } catch (NumberFormatException e) {
7656 reportSettingsProblem(Log.WARN,
7657 "Error in package manager settings: <cert> "
7658 + "index " + index + " is not a number at "
7659 + parser.getPositionDescription());
7660 }
7661 } else {
7662 reportSettingsProblem(Log.WARN,
7663 "Error in package manager settings: <cert> has"
7664 + " no index at " + parser.getPositionDescription());
7665 }
7666 } else {
7667 reportSettingsProblem(Log.WARN,
7668 "Error in package manager settings: too "
7669 + "many <cert> tags, expected " + count
7670 + " at " + parser.getPositionDescription());
7671 }
7672 } else {
7673 reportSettingsProblem(Log.WARN,
7674 "Unknown element under <cert>: "
7675 + parser.getName());
7676 }
7677 XmlUtils.skipCurrentTag(parser);
7678 }
7679
7680 if (pos < count) {
7681 // Should never happen -- there is an error in the written
7682 // settings -- but if it does we don't want to generate
7683 // a bad array.
7684 Signature[] newSigs = new Signature[pos];
7685 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
7686 mSignatures = newSigs;
7687 }
7688 }
7689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007690 private void assignSignatures(Signature[] sigs) {
7691 if (sigs == null) {
7692 mSignatures = null;
7693 return;
7694 }
7695 mSignatures = new Signature[sigs.length];
7696 for (int i=0; i<sigs.length; i++) {
7697 mSignatures[i] = sigs[i];
7698 }
7699 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007701 @Override
7702 public String toString() {
7703 StringBuffer buf = new StringBuffer(128);
7704 buf.append("PackageSignatures{");
7705 buf.append(Integer.toHexString(System.identityHashCode(this)));
7706 buf.append(" [");
7707 if (mSignatures != null) {
7708 for (int i=0; i<mSignatures.length; i++) {
7709 if (i > 0) buf.append(", ");
7710 buf.append(Integer.toHexString(
7711 System.identityHashCode(mSignatures[i])));
7712 }
7713 }
7714 buf.append("]}");
7715 return buf.toString();
7716 }
7717 }
7718
7719 static class PreferredActivity extends IntentFilter {
7720 final int mMatch;
7721 final String[] mSetPackages;
7722 final String[] mSetClasses;
7723 final String[] mSetComponents;
7724 final ComponentName mActivity;
7725 final String mShortActivity;
7726 String mParseError;
7727
7728 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
7729 ComponentName activity) {
7730 super(filter);
7731 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
7732 mActivity = activity;
7733 mShortActivity = activity.flattenToShortString();
7734 mParseError = null;
7735 if (set != null) {
7736 final int N = set.length;
7737 String[] myPackages = new String[N];
7738 String[] myClasses = new String[N];
7739 String[] myComponents = new String[N];
7740 for (int i=0; i<N; i++) {
7741 ComponentName cn = set[i];
7742 if (cn == null) {
7743 mSetPackages = null;
7744 mSetClasses = null;
7745 mSetComponents = null;
7746 return;
7747 }
7748 myPackages[i] = cn.getPackageName().intern();
7749 myClasses[i] = cn.getClassName().intern();
7750 myComponents[i] = cn.flattenToShortString().intern();
7751 }
7752 mSetPackages = myPackages;
7753 mSetClasses = myClasses;
7754 mSetComponents = myComponents;
7755 } else {
7756 mSetPackages = null;
7757 mSetClasses = null;
7758 mSetComponents = null;
7759 }
7760 }
7761
7762 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
7763 IOException {
7764 mShortActivity = parser.getAttributeValue(null, "name");
7765 mActivity = ComponentName.unflattenFromString(mShortActivity);
7766 if (mActivity == null) {
7767 mParseError = "Bad activity name " + mShortActivity;
7768 }
7769 String matchStr = parser.getAttributeValue(null, "match");
7770 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
7771 String setCountStr = parser.getAttributeValue(null, "set");
7772 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
7773
7774 String[] myPackages = setCount > 0 ? new String[setCount] : null;
7775 String[] myClasses = setCount > 0 ? new String[setCount] : null;
7776 String[] myComponents = setCount > 0 ? new String[setCount] : null;
7777
7778 int setPos = 0;
7779
7780 int outerDepth = parser.getDepth();
7781 int type;
7782 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7783 && (type != XmlPullParser.END_TAG
7784 || parser.getDepth() > outerDepth)) {
7785 if (type == XmlPullParser.END_TAG
7786 || type == XmlPullParser.TEXT) {
7787 continue;
7788 }
7789
7790 String tagName = parser.getName();
7791 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
7792 // + parser.getDepth() + " tag=" + tagName);
7793 if (tagName.equals("set")) {
7794 String name = parser.getAttributeValue(null, "name");
7795 if (name == null) {
7796 if (mParseError == null) {
7797 mParseError = "No name in set tag in preferred activity "
7798 + mShortActivity;
7799 }
7800 } else if (setPos >= setCount) {
7801 if (mParseError == null) {
7802 mParseError = "Too many set tags in preferred activity "
7803 + mShortActivity;
7804 }
7805 } else {
7806 ComponentName cn = ComponentName.unflattenFromString(name);
7807 if (cn == null) {
7808 if (mParseError == null) {
7809 mParseError = "Bad set name " + name + " in preferred activity "
7810 + mShortActivity;
7811 }
7812 } else {
7813 myPackages[setPos] = cn.getPackageName();
7814 myClasses[setPos] = cn.getClassName();
7815 myComponents[setPos] = name;
7816 setPos++;
7817 }
7818 }
7819 XmlUtils.skipCurrentTag(parser);
7820 } else if (tagName.equals("filter")) {
7821 //Log.i(TAG, "Starting to parse filter...");
7822 readFromXml(parser);
7823 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
7824 // + parser.getDepth() + " tag=" + parser.getName());
7825 } else {
7826 reportSettingsProblem(Log.WARN,
7827 "Unknown element under <preferred-activities>: "
7828 + parser.getName());
7829 XmlUtils.skipCurrentTag(parser);
7830 }
7831 }
7832
7833 if (setPos != setCount) {
7834 if (mParseError == null) {
7835 mParseError = "Not enough set tags (expected " + setCount
7836 + " but found " + setPos + ") in " + mShortActivity;
7837 }
7838 }
7839
7840 mSetPackages = myPackages;
7841 mSetClasses = myClasses;
7842 mSetComponents = myComponents;
7843 }
7844
7845 public void writeToXml(XmlSerializer serializer) throws IOException {
7846 final int NS = mSetClasses != null ? mSetClasses.length : 0;
7847 serializer.attribute(null, "name", mShortActivity);
7848 serializer.attribute(null, "match", Integer.toHexString(mMatch));
7849 serializer.attribute(null, "set", Integer.toString(NS));
7850 for (int s=0; s<NS; s++) {
7851 serializer.startTag(null, "set");
7852 serializer.attribute(null, "name", mSetComponents[s]);
7853 serializer.endTag(null, "set");
7854 }
7855 serializer.startTag(null, "filter");
7856 super.writeToXml(serializer);
7857 serializer.endTag(null, "filter");
7858 }
7859
7860 boolean sameSet(List<ResolveInfo> query, int priority) {
7861 if (mSetPackages == null) return false;
7862 final int NQ = query.size();
7863 final int NS = mSetPackages.length;
7864 int numMatch = 0;
7865 for (int i=0; i<NQ; i++) {
7866 ResolveInfo ri = query.get(i);
7867 if (ri.priority != priority) continue;
7868 ActivityInfo ai = ri.activityInfo;
7869 boolean good = false;
7870 for (int j=0; j<NS; j++) {
7871 if (mSetPackages[j].equals(ai.packageName)
7872 && mSetClasses[j].equals(ai.name)) {
7873 numMatch++;
7874 good = true;
7875 break;
7876 }
7877 }
7878 if (!good) return false;
7879 }
7880 return numMatch == NS;
7881 }
7882 }
7883
7884 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007885 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 HashSet<String> grantedPermissions = new HashSet<String>();
7888 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007890 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007891 setFlags(pkgFlags);
7892 }
7893
Kenny Root291e78c2011-01-13 14:53:17 -08007894 GrantedPermissions(GrantedPermissions base) {
7895 pkgFlags = base.pkgFlags;
7896 grantedPermissions = (HashSet<String>) base.grantedPermissions.clone();
Kenny Rootbd392c52011-01-14 10:34:56 -08007897
7898 if (base.gids != null) {
7899 gids = base.gids.clone();
7900 }
Kenny Root291e78c2011-01-13 14:53:17 -08007901 }
7902
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007903 void setFlags(int pkgFlags) {
Jeff Brown07330792010-03-30 19:57:08 -07007904 this.pkgFlags = pkgFlags & (
7905 ApplicationInfo.FLAG_SYSTEM |
7906 ApplicationInfo.FLAG_FORWARD_LOCK |
Dianne Hackborn3b81bc12011-01-15 11:50:52 -08007907 ApplicationInfo.FLAG_EXTERNAL_STORAGE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007908 }
7909 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 /**
7912 * Settings base class for pending and resolved classes.
7913 */
7914 static class PackageSettingBase extends GrantedPermissions {
7915 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007916 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007917 File codePath;
7918 String codePathString;
7919 File resourcePath;
7920 String resourcePathString;
Kenny Root85387d72010-08-26 10:13:11 -07007921 String nativeLibraryPathString;
Kenny Root7d794fb2010-09-13 16:29:49 -07007922 long timeStamp;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07007923 long firstInstallTime;
7924 long lastUpdateTime;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007925 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007927 boolean uidError;
Kenny Root291e78c2011-01-13 14:53:17 -08007928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929 PackageSignatures signatures = new PackageSignatures();
7930
7931 boolean permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007932 boolean haveGids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007933
Dianne Hackborne7f97212011-02-24 14:40:20 -08007934 // Whether this package is currently stopped, thus can not be
7935 // started until explicitly launched by the user.
7936 public boolean stopped;
7937
7938 // Set to true if we have never launched this app.
7939 public boolean notLaunched;
7940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007941 /* Explicitly disabled components */
7942 HashSet<String> disabledComponents = new HashSet<String>(0);
7943 /* Explicitly enabled components */
7944 HashSet<String> enabledComponents = new HashSet<String>(0);
7945 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7946 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007947
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007948 PackageSettingBase origPackage;
7949
Jacek Surazski65e13172009-04-28 15:26:38 +02007950 /* package name of the app that installed this package */
7951 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007952
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007953 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07007954 String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 super(pkgFlags);
7956 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007957 this.realName = realName;
Kenny Root806cc132010-09-12 08:34:19 -07007958 init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007959 }
7960
Kenny Root291e78c2011-01-13 14:53:17 -08007961 /**
7962 * New instance of PackageSetting with one-level-deep cloning.
7963 */
7964 PackageSettingBase(PackageSettingBase base) {
7965 super(base);
7966
7967 name = base.name;
7968 realName = base.realName;
7969 codePath = base.codePath;
7970 codePathString = base.codePathString;
7971 resourcePath = base.resourcePath;
7972 resourcePathString = base.resourcePathString;
7973 nativeLibraryPathString = base.nativeLibraryPathString;
Kenny Root291e78c2011-01-13 14:53:17 -08007974 timeStamp = base.timeStamp;
7975 firstInstallTime = base.firstInstallTime;
7976 lastUpdateTime = base.lastUpdateTime;
7977 versionCode = base.versionCode;
7978
7979 uidError = base.uidError;
7980
7981 signatures = new PackageSignatures(base.signatures);
7982
7983 permissionsFixed = base.permissionsFixed;
7984 haveGids = base.haveGids;
Dianne Hackborne7f97212011-02-24 14:40:20 -08007985 stopped = base.stopped;
7986 notLaunched = base.notLaunched;
Kenny Root291e78c2011-01-13 14:53:17 -08007987
7988 disabledComponents = (HashSet<String>) base.disabledComponents.clone();
7989
7990 enabledComponents = (HashSet<String>) base.enabledComponents.clone();
7991
7992 enabled = base.enabled;
7993 installStatus = base.installStatus;
7994
7995 origPackage = base.origPackage;
7996
7997 installerPackageName = base.installerPackageName;
7998 }
7999
Kenny Root806cc132010-09-12 08:34:19 -07008000 void init(File codePath, File resourcePath, String nativeLibraryPathString,
8001 int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008002 this.codePath = codePath;
8003 this.codePathString = codePath.toString();
8004 this.resourcePath = resourcePath;
8005 this.resourcePathString = resourcePath.toString();
Kenny Root806cc132010-09-12 08:34:19 -07008006 this.nativeLibraryPathString = nativeLibraryPathString;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008007 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 }
Kenny Root85387d72010-08-26 10:13:11 -07008009
Jacek Surazski65e13172009-04-28 15:26:38 +02008010 public void setInstallerPackageName(String packageName) {
8011 installerPackageName = packageName;
8012 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008013
Jacek Surazski65e13172009-04-28 15:26:38 +02008014 String getInstallerPackageName() {
8015 return installerPackageName;
8016 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 public void setInstallStatus(int newStatus) {
8019 installStatus = newStatus;
8020 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008022 public int getInstallStatus() {
8023 return installStatus;
8024 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 public void setTimeStamp(long newStamp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008027 timeStamp = newStamp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 }
8029
Kenny Root291e78c2011-01-13 14:53:17 -08008030 /**
8031 * Make a shallow copy of this package settings.
8032 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 public void copyFrom(PackageSettingBase base) {
8034 grantedPermissions = base.grantedPermissions;
8035 gids = base.gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 timeStamp = base.timeStamp;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07008038 firstInstallTime = base.firstInstallTime;
8039 lastUpdateTime = base.lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008040 signatures = base.signatures;
8041 permissionsFixed = base.permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07008042 haveGids = base.haveGids;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008043 stopped = base.stopped;
8044 notLaunched = base.notLaunched;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 disabledComponents = base.disabledComponents;
8046 enabledComponents = base.enabledComponents;
8047 enabled = base.enabled;
8048 installStatus = base.installStatus;
8049 }
8050
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008051 boolean enableComponentLP(String componentClassName) {
8052 boolean changed = disabledComponents.remove(componentClassName);
8053 changed |= enabledComponents.add(componentClassName);
8054 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008055 }
8056
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008057 boolean disableComponentLP(String componentClassName) {
8058 boolean changed = enabledComponents.remove(componentClassName);
8059 changed |= disabledComponents.add(componentClassName);
8060 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 }
8062
Dianne Hackbornd7c09682010-03-30 10:42:20 -07008063 boolean restoreComponentLP(String componentClassName) {
8064 boolean changed = enabledComponents.remove(componentClassName);
8065 changed |= disabledComponents.remove(componentClassName);
8066 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008067 }
8068
8069 int currentEnabledStateLP(String componentName) {
8070 if (enabledComponents.contains(componentName)) {
8071 return COMPONENT_ENABLED_STATE_ENABLED;
8072 } else if (disabledComponents.contains(componentName)) {
8073 return COMPONENT_ENABLED_STATE_DISABLED;
8074 } else {
8075 return COMPONENT_ENABLED_STATE_DEFAULT;
8076 }
8077 }
8078 }
8079
8080 /**
8081 * Settings data for a particular package we know about.
8082 */
8083 static final class PackageSetting extends PackageSettingBase {
8084 int userId;
8085 PackageParser.Package pkg;
8086 SharedUserSetting sharedUser;
8087
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008088 PackageSetting(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008089 String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
8090 super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
8091 pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008093
Kenny Root291e78c2011-01-13 14:53:17 -08008094 /**
8095 * New instance of PackageSetting replicating the original settings.
8096 * Note that it keeps the same PackageParser.Package instance.
8097 */
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008098 PackageSetting(PackageSetting orig) {
Kenny Root291e78c2011-01-13 14:53:17 -08008099 super(orig);
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008100
Kenny Root291e78c2011-01-13 14:53:17 -08008101 userId = orig.userId;
8102 pkg = orig.pkg;
8103 sharedUser = orig.sharedUser;
Kenny Root97ef63b2011-01-11 11:15:35 -08008104 }
8105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 @Override
8107 public String toString() {
8108 return "PackageSetting{"
8109 + Integer.toHexString(System.identityHashCode(this))
8110 + " " + name + "/" + userId + "}";
8111 }
8112 }
8113
8114 /**
8115 * Settings data for a particular shared user ID we know about.
8116 */
8117 static final class SharedUserSetting extends GrantedPermissions {
8118 final String name;
8119 int userId;
8120 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
8121 final PackageSignatures signatures = new PackageSignatures();
8122
8123 SharedUserSetting(String _name, int _pkgFlags) {
8124 super(_pkgFlags);
8125 name = _name;
8126 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 @Override
8129 public String toString() {
8130 return "SharedUserSetting{"
8131 + Integer.toHexString(System.identityHashCode(this))
8132 + " " + name + "/" + userId + "}";
8133 }
8134 }
8135
8136 /**
8137 * Holds information about dynamic settings.
8138 */
8139 private static final class Settings {
8140 private final File mSettingsFilename;
8141 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008142 private final File mPackageListFilename;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008143 private final File mStoppedPackagesFilename;
8144 private final File mBackupStoppedPackagesFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 private final HashMap<String, PackageSetting> mPackages =
8146 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 // List of replaced system applications
8148 final HashMap<String, PackageSetting> mDisabledSysPackages =
8149 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008150
Dianne Hackbornf22221f2010-04-05 18:35:42 -07008151 // These are the last platform API version we were using for
8152 // the apps installed on internal and external storage. It is
8153 // used to grant newer permissions one time during a system upgrade.
8154 int mInternalSdkPlatform;
8155 int mExternalSdkPlatform;
8156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008157 // The user's preferred activities associated with particular intent
8158 // filters.
8159 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
8160 new IntentResolver<PreferredActivity, PreferredActivity>() {
8161 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008162 protected String packageForFilter(PreferredActivity filter) {
8163 return filter.mActivity.getPackageName();
8164 }
8165 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008166 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008167 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008168 out.print(prefix); out.print(
8169 Integer.toHexString(System.identityHashCode(filter)));
8170 out.print(' ');
8171 out.print(filter.mActivity.flattenToShortString());
8172 out.print(" match=0x");
8173 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008175 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008176 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008177 out.print(prefix); out.print(" ");
8178 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 }
8180 }
8181 }
8182 };
8183 private final HashMap<String, SharedUserSetting> mSharedUsers =
8184 new HashMap<String, SharedUserSetting>();
8185 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
8186 private final SparseArray<Object> mOtherUserIds =
8187 new SparseArray<Object>();
8188
8189 // For reading/writing settings file.
8190 private final ArrayList<Signature> mPastSignatures =
8191 new ArrayList<Signature>();
8192
8193 // Mapping from permission names to info about them.
8194 final HashMap<String, BasePermission> mPermissions =
8195 new HashMap<String, BasePermission>();
8196
8197 // Mapping from permission tree names to info about them.
8198 final HashMap<String, BasePermission> mPermissionTrees =
8199 new HashMap<String, BasePermission>();
8200
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008201 // Packages that have been uninstalled and still need their external
8202 // storage data deleted.
8203 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
8204
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008205 // Packages that have been renamed since they were first installed.
8206 // Keys are the new names of the packages, values are the original
8207 // names. The packages appear everwhere else under their original
8208 // names.
8209 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
8210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211 private final StringBuilder mReadMessages = new StringBuilder();
8212
8213 private static final class PendingPackage extends PackageSettingBase {
8214 final int sharedId;
8215
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008216 PendingPackage(String name, String realName, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008217 String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) {
8218 super(name, realName, codePath, resourcePath, nativeLibraryPathString,
8219 pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 this.sharedId = sharedId;
8221 }
8222 }
8223 private final ArrayList<PendingPackage> mPendingPackages
8224 = new ArrayList<PendingPackage>();
8225
8226 Settings() {
8227 File dataDir = Environment.getDataDirectory();
8228 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08008229 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
8230 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008231 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008232 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008233 FileUtils.setPermissions(systemDir.toString(),
8234 FileUtils.S_IRWXU|FileUtils.S_IRWXG
8235 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
8236 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08008237 FileUtils.setPermissions(systemSecureDir.toString(),
8238 FileUtils.S_IRWXU|FileUtils.S_IRWXG
8239 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
8240 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008241 mSettingsFilename = new File(systemDir, "packages.xml");
8242 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008243 mPackageListFilename = new File(systemDir, "packages.list");
Dianne Hackborne7f97212011-02-24 14:40:20 -08008244 mStoppedPackagesFilename = new File(systemDir, "packages-stopped.xml");
8245 mBackupStoppedPackagesFilename = new File(systemDir, "packages-stopped-backup.xml");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008246 }
8247
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008248 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008249 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008250 String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008251 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008252 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Kenny Root806cc132010-09-12 08:34:19 -07008253 resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 return p;
8255 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008256
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008257 PackageSetting peekPackageLP(String name) {
8258 return mPackages.get(name);
8259 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 PackageSetting p = mPackages.get(name);
8261 if (p != null && p.codePath.getPath().equals(codePath)) {
8262 return p;
8263 }
8264 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008265 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008268 void setInstallStatus(String pkgName, int status) {
8269 PackageSetting p = mPackages.get(pkgName);
8270 if(p != null) {
8271 if(p.getInstallStatus() != status) {
8272 p.setInstallStatus(status);
8273 }
8274 }
8275 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008276
Jacek Surazski65e13172009-04-28 15:26:38 +02008277 void setInstallerPackageName(String pkgName,
8278 String installerPkgName) {
8279 PackageSetting p = mPackages.get(pkgName);
8280 if(p != null) {
8281 p.setInstallerPackageName(installerPkgName);
8282 }
8283 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008284
Jacek Surazski65e13172009-04-28 15:26:38 +02008285 String getInstallerPackageName(String pkgName) {
8286 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008287 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02008288 }
8289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 int getInstallStatus(String pkgName) {
8291 PackageSetting p = mPackages.get(pkgName);
8292 if(p != null) {
8293 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008295 return -1;
8296 }
8297
8298 SharedUserSetting getSharedUserLP(String name,
8299 int pkgFlags, boolean create) {
8300 SharedUserSetting s = mSharedUsers.get(name);
8301 if (s == null) {
8302 if (!create) {
8303 return null;
8304 }
8305 s = new SharedUserSetting(name, pkgFlags);
8306 if (MULTIPLE_APPLICATION_UIDS) {
8307 s.userId = newUserIdLP(s);
8308 } else {
8309 s.userId = FIRST_APPLICATION_UID;
8310 }
8311 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
8312 // < 0 means we couldn't assign a userid; fall out and return
8313 // s, which is currently null
8314 if (s.userId >= 0) {
8315 mSharedUsers.put(name, s);
8316 }
8317 }
8318
8319 return s;
8320 }
8321
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008322 boolean disableSystemPackageLP(String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 PackageSetting p = mPackages.get(name);
8324 if(p == null) {
8325 Log.w(TAG, "Package:"+name+" is not an installed package");
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008326 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 }
8328 PackageSetting dp = mDisabledSysPackages.get(name);
8329 // always make sure the system package code and resource paths dont change
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008330 if (dp == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008331 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
8332 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
8333 }
8334 mDisabledSysPackages.put(name, p);
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008335
8336 // a little trick... when we install the new package, we don't
8337 // want to modify the existing PackageSetting for the built-in
8338 // version. so at this point we need a new PackageSetting that
Kenny Root291e78c2011-01-13 14:53:17 -08008339 // is okay to muck with.
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008340 PackageSetting newp = new PackageSetting(p);
8341 replacePackageLP(name, newp);
8342 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 }
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008344 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008345 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008347 PackageSetting enableSystemPackageLP(String name) {
8348 PackageSetting p = mDisabledSysPackages.get(name);
8349 if(p == null) {
8350 Log.w(TAG, "Package:"+name+" is not disabled");
8351 return null;
8352 }
8353 // Reset flag in ApplicationInfo object
8354 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
8355 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
8356 }
Kenny Root806cc132010-09-12 08:34:19 -07008357 PackageSetting ret = addPackageLP(name, p.realName, p.codePath, p.resourcePath,
8358 p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 mDisabledSysPackages.remove(name);
8360 return ret;
8361 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008362
Kenny Root806cc132010-09-12 08:34:19 -07008363 PackageSetting addPackageLP(String name, String realName, File codePath, File resourcePath,
8364 String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008365 PackageSetting p = mPackages.get(name);
8366 if (p != null) {
8367 if (p.userId == uid) {
8368 return p;
8369 }
8370 reportSettingsProblem(Log.ERROR,
8371 "Adding duplicate package, keeping first: " + name);
8372 return null;
8373 }
Kenny Root806cc132010-09-12 08:34:19 -07008374 p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
8375 vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008376 p.userId = uid;
8377 if (addUserIdLP(uid, p, name)) {
8378 mPackages.put(name, p);
8379 return p;
8380 }
8381 return null;
8382 }
8383
8384 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
8385 SharedUserSetting s = mSharedUsers.get(name);
8386 if (s != null) {
8387 if (s.userId == uid) {
8388 return s;
8389 }
8390 reportSettingsProblem(Log.ERROR,
8391 "Adding duplicate shared user, keeping first: " + name);
8392 return null;
8393 }
8394 s = new SharedUserSetting(name, pkgFlags);
8395 s.userId = uid;
8396 if (addUserIdLP(uid, s, name)) {
8397 mSharedUsers.put(name, s);
8398 return s;
8399 }
8400 return null;
8401 }
8402
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008403 // Transfer ownership of permissions from one package to another.
8404 private void transferPermissions(String origPkg, String newPkg) {
8405 // Transfer ownership of permissions to the new package.
8406 for (int i=0; i<2; i++) {
8407 HashMap<String, BasePermission> permissions =
8408 i == 0 ? mPermissionTrees : mPermissions;
8409 for (BasePermission bp : permissions.values()) {
8410 if (origPkg.equals(bp.sourcePackage)) {
8411 if (DEBUG_UPGRADE) Log.v(TAG,
8412 "Moving permission " + bp.name
8413 + " from pkg " + bp.sourcePackage
8414 + " to " + newPkg);
8415 bp.sourcePackage = newPkg;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008416 bp.packageSetting = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008417 bp.perm = null;
8418 if (bp.pendingInfo != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008419 bp.pendingInfo.packageName = newPkg;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008420 }
8421 bp.uid = 0;
8422 bp.gids = null;
8423 }
8424 }
8425 }
8426 }
8427
8428 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008429 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Kenny Root806cc132010-09-12 08:34:19 -07008430 String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 PackageSetting p = mPackages.get(name);
8432 if (p != null) {
8433 if (!p.codePath.equals(codePath)) {
8434 // Check to see if its a disabled system app
Kenny Rootbd135c12010-10-05 12:26:27 -07008435 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07008436 // This is an updated system app with versions in both system
8437 // and data partition. Just let the most recent version
8438 // take precedence.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008439 Slog.w(TAG, "Trying to update system app code path from " +
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008440 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07008441 } else {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08008442 // Just a change in the code path is not an issue, but
8443 // let's log a message about it.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008444 Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008445 + " to " + codePath + "; Retaining data and using new");
Kenny Rootbd135c12010-10-05 12:26:27 -07008446 /*
8447 * Since we've changed paths, we need to prefer the new
8448 * native library path over the one stored in the
8449 * package settings since we might have moved from
8450 * internal to external storage or vice versa.
8451 */
8452 p.nativeLibraryPathString = nativeLibraryPathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008454 }
8455 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008456 reportSettingsProblem(Log.WARN,
8457 "Package " + name + " shared user changed from "
8458 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
8459 + " to "
8460 + (sharedUser != null ? sharedUser.name : "<nothing>")
8461 + "; replacing with new");
8462 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008463 } else {
8464 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
8465 // If what we are scanning is a system package, then
8466 // make it so, regardless of whether it was previously
8467 // installed only in the data partition.
8468 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 }
8471 }
8472 if (p == null) {
8473 // Create a new PackageSettings entry. this can end up here because
8474 // of code path mismatch or user id mismatch of an updated system partition
8475 if (!create) {
8476 return null;
8477 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008478 if (origPackage != null) {
8479 // We are consuming the data from an existing package.
Kenny Root806cc132010-09-12 08:34:19 -07008480 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
8481 nativeLibraryPathString, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008482 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
8483 + " is adopting original package " + origPackage.name);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008484 // Note that we will retain the new package's signature so
8485 // that we can keep its data.
8486 PackageSignatures s = p.signatures;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008487 p.copyFrom(origPackage);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008488 p.signatures = s;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008489 p.sharedUser = origPackage.sharedUser;
8490 p.userId = origPackage.userId;
8491 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008492 mRenamedPackages.put(name, origPackage.name);
8493 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008494 // Update new package state.
8495 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 } else {
Kenny Root806cc132010-09-12 08:34:19 -07008497 p = new PackageSetting(name, realName, codePath, resourcePath,
8498 nativeLibraryPathString, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008499 p.setTimeStamp(codePath.lastModified());
8500 p.sharedUser = sharedUser;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008501 // If this is not a system app, it starts out stopped.
8502 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8503 if (DEBUG_STOPPED) {
8504 RuntimeException e = new RuntimeException("here");
8505 e.fillInStackTrace();
8506 Slog.i(TAG, "Stopping package " + name, e);
8507 }
8508 p.stopped = true;
8509 p.notLaunched = true;
8510 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008511 if (sharedUser != null) {
8512 p.userId = sharedUser.userId;
8513 } else if (MULTIPLE_APPLICATION_UIDS) {
8514 // Clone the setting here for disabled system packages
8515 PackageSetting dis = mDisabledSysPackages.get(name);
8516 if (dis != null) {
8517 // For disabled packages a new setting is created
8518 // from the existing user id. This still has to be
8519 // added to list of user id's
8520 // Copy signatures from previous setting
8521 if (dis.signatures.mSignatures != null) {
8522 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
8523 }
8524 p.userId = dis.userId;
8525 // Clone permissions
8526 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008527 // Clone component info
8528 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
8529 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
8530 // Add new setting to list of user ids
8531 addUserIdLP(p.userId, p, name);
8532 } else {
8533 // Assign new user id
8534 p.userId = newUserIdLP(p);
8535 }
8536 } else {
8537 p.userId = FIRST_APPLICATION_UID;
8538 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008539 }
8540 if (p.userId < 0) {
8541 reportSettingsProblem(Log.WARN,
8542 "Package " + name + " could not be assigned a valid uid");
8543 return null;
8544 }
8545 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008546 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008548 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 }
8550 }
8551 return p;
8552 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008553
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008554 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008555 p.pkg = pkg;
Dianne Hackborn46730fc2010-07-24 16:32:42 -07008556 pkg.mSetEnabled = p.enabled;
Dianne Hackborne7f97212011-02-24 14:40:20 -08008557 pkg.mSetStopped = p.stopped;
Kenny Root85387d72010-08-26 10:13:11 -07008558 final String codePath = pkg.applicationInfo.sourceDir;
8559 final String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008560 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008561 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008562 Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008563 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008564 p.codePath = new File(codePath);
8565 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008566 }
8567 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008568 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008569 Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008570 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008571 p.resourcePath = new File(resourcePath);
8572 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008573 }
Kenny Root85387d72010-08-26 10:13:11 -07008574 // Update the native library path if needed
8575 final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
8576 if (nativeLibraryPath != null
8577 && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
8578 p.nativeLibraryPathString = nativeLibraryPath;
8579 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008580 // Update version code if needed
8581 if (pkg.mVersionCode != p.versionCode) {
8582 p.versionCode = pkg.mVersionCode;
8583 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008584 // Update signatures if needed.
8585 if (p.signatures.mSignatures == null) {
8586 p.signatures.assignSignatures(pkg.mSignatures);
8587 }
8588 // If this app defines a shared user id initialize
8589 // the shared user signatures as well.
8590 if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
8591 p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
8592 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008593 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
8594 }
8595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008596 // Utility method that adds a PackageSetting to mPackages and
8597 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008598 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008599 SharedUserSetting sharedUser) {
8600 mPackages.put(name, p);
8601 if (sharedUser != null) {
8602 if (p.sharedUser != null && p.sharedUser != sharedUser) {
8603 reportSettingsProblem(Log.ERROR,
8604 "Package " + p.name + " was user "
8605 + p.sharedUser + " but is now " + sharedUser
8606 + "; I am not changing its files so it will probably fail!");
8607 p.sharedUser.packages.remove(p);
8608 } else if (p.userId != sharedUser.userId) {
8609 reportSettingsProblem(Log.ERROR,
8610 "Package " + p.name + " was user id " + p.userId
8611 + " but is now user " + sharedUser
8612 + " with id " + sharedUser.userId
8613 + "; I am not changing its files so it will probably fail!");
8614 }
8615
8616 sharedUser.packages.add(p);
8617 p.sharedUser = sharedUser;
8618 p.userId = sharedUser.userId;
8619 }
8620 }
8621
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008622 /*
8623 * Update the shared user setting when a package using
8624 * specifying the shared user id is removed. The gids
8625 * associated with each permission of the deleted package
8626 * are removed from the shared user's gid list only if its
8627 * not in use by other permissions of packages in the
8628 * shared user setting.
8629 */
8630 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008631 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008632 Slog.i(TAG, "Trying to update info for null package. Just ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 return;
8634 }
8635 // No sharedUserId
8636 if (deletedPs.sharedUser == null) {
8637 return;
8638 }
8639 SharedUserSetting sus = deletedPs.sharedUser;
8640 // Update permissions
8641 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
8642 boolean used = false;
8643 if (!sus.grantedPermissions.contains (eachPerm)) {
8644 continue;
8645 }
8646 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008647 if (pkg.pkg != null &&
Dianne Hackbornf657b632010-03-22 18:08:07 -07008648 !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008649 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008650 used = true;
8651 break;
8652 }
8653 }
8654 if (!used) {
8655 // can safely delete this permission from list
8656 sus.grantedPermissions.remove(eachPerm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 }
8658 }
8659 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008660 int newGids[] = globalGids;
8661 for (String eachPerm : sus.grantedPermissions) {
8662 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008663 if (bp != null) {
8664 newGids = appendInts(newGids, bp.gids);
8665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 }
8667 sus.gids = newGids;
8668 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 private int removePackageLP(String name) {
8671 PackageSetting p = mPackages.get(name);
8672 if (p != null) {
8673 mPackages.remove(name);
8674 if (p.sharedUser != null) {
8675 p.sharedUser.packages.remove(p);
8676 if (p.sharedUser.packages.size() == 0) {
8677 mSharedUsers.remove(p.sharedUser.name);
8678 removeUserIdLP(p.sharedUser.userId);
8679 return p.sharedUser.userId;
8680 }
8681 } else {
8682 removeUserIdLP(p.userId);
8683 return p.userId;
8684 }
8685 }
8686 return -1;
8687 }
8688
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008689 private void replacePackageLP(String name, PackageSetting newp) {
8690 PackageSetting p = mPackages.get(name);
8691 if (p != null) {
8692 if (p.sharedUser != null) {
8693 p.sharedUser.packages.remove(p);
8694 p.sharedUser.packages.add(newp);
8695 } else {
8696 replaceUserIdLP(p.userId, newp);
8697 }
8698 }
8699 mPackages.put(name, newp);
8700 }
8701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 private boolean addUserIdLP(int uid, Object obj, Object name) {
8703 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
8704 return false;
8705 }
8706
8707 if (uid >= FIRST_APPLICATION_UID) {
8708 int N = mUserIds.size();
8709 final int index = uid - FIRST_APPLICATION_UID;
8710 while (index >= N) {
8711 mUserIds.add(null);
8712 N++;
8713 }
8714 if (mUserIds.get(index) != null) {
8715 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008716 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008717 + " name=" + name);
8718 return false;
8719 }
8720 mUserIds.set(index, obj);
8721 } else {
8722 if (mOtherUserIds.get(uid) != null) {
8723 reportSettingsProblem(Log.ERROR,
8724 "Adding duplicate shared id: " + uid
8725 + " name=" + name);
8726 return false;
8727 }
8728 mOtherUserIds.put(uid, obj);
8729 }
8730 return true;
8731 }
8732
8733 public Object getUserIdLP(int uid) {
8734 if (uid >= FIRST_APPLICATION_UID) {
8735 int N = mUserIds.size();
8736 final int index = uid - FIRST_APPLICATION_UID;
8737 return index < N ? mUserIds.get(index) : null;
8738 } else {
8739 return mOtherUserIds.get(uid);
8740 }
8741 }
8742
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008743 private Set<String> findPackagesWithFlag(int flag) {
8744 Set<String> ret = new HashSet<String>();
8745 for (PackageSetting ps : mPackages.values()) {
8746 // Has to match atleast all the flag bits set on flag
8747 if ((ps.pkgFlags & flag) == flag) {
8748 ret.add(ps.name);
8749 }
8750 }
8751 return ret;
8752 }
8753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 private void removeUserIdLP(int uid) {
8755 if (uid >= FIRST_APPLICATION_UID) {
8756 int N = mUserIds.size();
8757 final int index = uid - FIRST_APPLICATION_UID;
8758 if (index < N) mUserIds.set(index, null);
8759 } else {
8760 mOtherUserIds.remove(uid);
8761 }
8762 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008763
Dianne Hackborn690d20b2010-12-22 14:03:29 -08008764 private void replaceUserIdLP(int uid, Object obj) {
8765 if (uid >= FIRST_APPLICATION_UID) {
8766 int N = mUserIds.size();
8767 final int index = uid - FIRST_APPLICATION_UID;
8768 if (index < N) mUserIds.set(index, obj);
8769 } else {
8770 mOtherUserIds.put(uid, obj);
8771 }
8772 }
8773
Dianne Hackborne7f97212011-02-24 14:40:20 -08008774 void writeStoppedLP() {
8775 // Keep the old stopped packages around until we know the new ones have
8776 // been successfully written.
8777 if (mStoppedPackagesFilename.exists()) {
8778 // Presence of backup settings file indicates that we failed
8779 // to persist packages earlier. So preserve the older
8780 // backup for future reference since the current packages
8781 // might have been corrupted.
8782 if (!mBackupStoppedPackagesFilename.exists()) {
8783 if (!mStoppedPackagesFilename.renameTo(mBackupStoppedPackagesFilename)) {
8784 Log.wtf(TAG, "Unable to backup package manager stopped packages, "
8785 + "current changes will be lost at reboot");
8786 return;
8787 }
8788 } else {
8789 mStoppedPackagesFilename.delete();
8790 Slog.w(TAG, "Preserving older stopped packages backup");
8791 }
8792 }
8793
8794 try {
8795 FileOutputStream fstr = new FileOutputStream(mStoppedPackagesFilename);
8796 BufferedOutputStream str = new BufferedOutputStream(fstr);
8797
8798 //XmlSerializer serializer = XmlUtils.serializerInstance();
8799 XmlSerializer serializer = new FastXmlSerializer();
8800 serializer.setOutput(str, "utf-8");
8801 serializer.startDocument(null, true);
8802 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
8803
8804 serializer.startTag(null, "stopped-packages");
8805
8806 for (PackageSetting pkg : mPackages.values()) {
8807 if (pkg.stopped) {
8808 serializer.startTag(null, "pkg");
8809 serializer.attribute(null, "name", pkg.name);
8810 if (pkg.notLaunched) {
8811 serializer.attribute(null, "nl", "1");
8812 }
8813 serializer.endTag(null, "pkg");
8814 }
8815 }
8816
8817 serializer.endTag(null, "stopped-packages");
8818
8819 serializer.endDocument();
8820
8821 str.flush();
8822 FileUtils.sync(fstr);
8823 str.close();
8824
8825 // New settings successfully written, old ones are no longer
8826 // needed.
8827 mBackupStoppedPackagesFilename.delete();
8828 FileUtils.setPermissions(mStoppedPackagesFilename.toString(),
8829 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8830 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8831 |FileUtils.S_IROTH,
8832 -1, -1);
8833
8834 // Done, all is good!
8835 return;
8836
8837 } catch(java.io.IOException e) {
8838 Log.wtf(TAG, "Unable to write package manager stopped packages, "
8839 + " current changes will be lost at reboot", e);
8840 }
8841
8842 // Clean up partially written files
8843 if (mStoppedPackagesFilename.exists()) {
8844 if (!mStoppedPackagesFilename.delete()) {
8845 Log.i(TAG, "Failed to clean up mangled file: " + mStoppedPackagesFilename);
8846 }
8847 }
8848 }
8849
8850 // Note: assumed "stopped" field is already cleared in all packages.
8851 void readStoppedLP() {
8852 FileInputStream str = null;
8853 if (mBackupStoppedPackagesFilename.exists()) {
8854 try {
8855 str = new FileInputStream(mBackupStoppedPackagesFilename);
8856 mReadMessages.append("Reading from backup stopped packages file\n");
8857 reportSettingsProblem(Log.INFO, "Need to read from backup stopped packages file");
8858 if (mSettingsFilename.exists()) {
8859 // If both the backup and normal file exist, we
8860 // ignore the normal one since it might have been
8861 // corrupted.
8862 Slog.w(TAG, "Cleaning up stopped packages file "
8863 + mStoppedPackagesFilename);
8864 mStoppedPackagesFilename.delete();
8865 }
8866 } catch (java.io.IOException e) {
8867 // We'll try for the normal settings file.
8868 }
8869 }
8870
8871 try {
8872 if (str == null) {
8873 if (!mStoppedPackagesFilename.exists()) {
8874 mReadMessages.append("No stopped packages file found\n");
8875 reportSettingsProblem(Log.INFO, "No stopped packages file file; "
8876 + "assuming all started");
8877 // At first boot, make sure no packages are stopped.
8878 // We usually want to have third party apps initialize
8879 // in the stopped state, but not at first boot.
8880 for (PackageSetting pkg : mPackages.values()) {
8881 pkg.stopped = false;
8882 pkg.notLaunched = false;
8883 }
8884 return;
8885 }
8886 str = new FileInputStream(mStoppedPackagesFilename);
8887 }
8888 XmlPullParser parser = Xml.newPullParser();
8889 parser.setInput(str, null);
8890
8891 int type;
8892 while ((type=parser.next()) != XmlPullParser.START_TAG
8893 && type != XmlPullParser.END_DOCUMENT) {
8894 ;
8895 }
8896
8897 if (type != XmlPullParser.START_TAG) {
8898 mReadMessages.append("No start tag found in stopped packages file\n");
8899 reportSettingsProblem(Log.WARN,
8900 "No start tag found in package manager stopped packages");
8901 return;
8902 }
8903
8904 int outerDepth = parser.getDepth();
8905 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8906 && (type != XmlPullParser.END_TAG
8907 || parser.getDepth() > outerDepth)) {
8908 if (type == XmlPullParser.END_TAG
8909 || type == XmlPullParser.TEXT) {
8910 continue;
8911 }
8912
8913 String tagName = parser.getName();
8914 if (tagName.equals("pkg")) {
8915 String name = parser.getAttributeValue(null, "name");
8916 PackageSetting ps = mPackages.get(name);
8917 if (ps != null) {
8918 ps.stopped = true;
8919 if ("1".equals(parser.getAttributeValue(null, "nl"))) {
8920 ps.notLaunched = true;
8921 }
8922 } else {
8923 Slog.w(TAG, "No package known for stopped package: " + name);
8924 }
8925 XmlUtils.skipCurrentTag(parser);
8926 } else {
8927 Slog.w(TAG, "Unknown element under <stopped-packages>: "
8928 + parser.getName());
8929 XmlUtils.skipCurrentTag(parser);
8930 }
8931 }
8932
8933 str.close();
8934
8935 } catch(XmlPullParserException e) {
8936 mReadMessages.append("Error reading: " + e.toString());
8937 reportSettingsProblem(Log.ERROR, "Error reading stopped packages: " + e);
8938 Log.wtf(TAG, "Error reading package manager stopped packages", e);
8939
8940 } catch(java.io.IOException e) {
8941 mReadMessages.append("Error reading: " + e.toString());
8942 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
8943 Log.wtf(TAG, "Error reading package manager stopped packages", e);
8944
8945 }
8946 }
8947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008948 void writeLP() {
8949 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
8950
8951 // Keep the old settings around until we know the new ones have
8952 // been successfully written.
8953 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008954 // Presence of backup settings file indicates that we failed
8955 // to persist settings earlier. So preserve the older
8956 // backup for future reference since the current settings
8957 // might have been corrupted.
8958 if (!mBackupSettingsFilename.exists()) {
8959 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08008960 Log.wtf(TAG, "Unable to backup package manager settings, "
8961 + " current changes will be lost at reboot");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008962 return;
8963 }
8964 } else {
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07008965 mSettingsFilename.delete();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008966 Slog.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07008967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008968 }
8969
8970 mPastSignatures.clear();
8971
8972 try {
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07008973 FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
8974 BufferedOutputStream str = new BufferedOutputStream(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008975
8976 //XmlSerializer serializer = XmlUtils.serializerInstance();
8977 XmlSerializer serializer = new FastXmlSerializer();
8978 serializer.setOutput(str, "utf-8");
8979 serializer.startDocument(null, true);
8980 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
8981
8982 serializer.startTag(null, "packages");
8983
Dianne Hackbornf22221f2010-04-05 18:35:42 -07008984 serializer.startTag(null, "last-platform-version");
8985 serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
8986 serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
8987 serializer.endTag(null, "last-platform-version");
8988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008989 serializer.startTag(null, "permission-trees");
8990 for (BasePermission bp : mPermissionTrees.values()) {
8991 writePermission(serializer, bp);
8992 }
8993 serializer.endTag(null, "permission-trees");
8994
8995 serializer.startTag(null, "permissions");
8996 for (BasePermission bp : mPermissions.values()) {
8997 writePermission(serializer, bp);
8998 }
8999 serializer.endTag(null, "permissions");
9000
9001 for (PackageSetting pkg : mPackages.values()) {
9002 writePackage(serializer, pkg);
9003 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 for (PackageSetting pkg : mDisabledSysPackages.values()) {
9006 writeDisabledSysPackage(serializer, pkg);
9007 }
9008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 serializer.startTag(null, "preferred-activities");
9010 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
9011 serializer.startTag(null, "item");
9012 pa.writeToXml(serializer);
9013 serializer.endTag(null, "item");
9014 }
9015 serializer.endTag(null, "preferred-activities");
9016
9017 for (SharedUserSetting usr : mSharedUsers.values()) {
9018 serializer.startTag(null, "shared-user");
9019 serializer.attribute(null, "name", usr.name);
9020 serializer.attribute(null, "userId",
9021 Integer.toString(usr.userId));
9022 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
9023 serializer.startTag(null, "perms");
9024 for (String name : usr.grantedPermissions) {
9025 serializer.startTag(null, "item");
9026 serializer.attribute(null, "name", name);
9027 serializer.endTag(null, "item");
9028 }
9029 serializer.endTag(null, "perms");
9030 serializer.endTag(null, "shared-user");
9031 }
9032
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009033 if (mPackagesToBeCleaned.size() > 0) {
9034 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
9035 serializer.startTag(null, "cleaning-package");
9036 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
9037 serializer.endTag(null, "cleaning-package");
9038 }
9039 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009040
9041 if (mRenamedPackages.size() > 0) {
9042 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
9043 serializer.startTag(null, "renamed-package");
9044 serializer.attribute(null, "new", e.getKey());
9045 serializer.attribute(null, "old", e.getValue());
9046 serializer.endTag(null, "renamed-package");
9047 }
9048 }
9049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009050 serializer.endTag(null, "packages");
9051
9052 serializer.endDocument();
9053
9054 str.flush();
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07009055 FileUtils.sync(fstr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009056 str.close();
9057
9058 // New settings successfully written, old ones are no longer
9059 // needed.
9060 mBackupSettingsFilename.delete();
9061 FileUtils.setPermissions(mSettingsFilename.toString(),
9062 FileUtils.S_IRUSR|FileUtils.S_IWUSR
9063 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
9064 |FileUtils.S_IROTH,
9065 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009066
9067 // Write package list file now, use a JournaledFile.
9068 //
9069 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
9070 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
9071
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07009072 fstr = new FileOutputStream(journal.chooseForWrite());
9073 str = new BufferedOutputStream(fstr);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009074 try {
9075 StringBuilder sb = new StringBuilder();
9076 for (PackageSetting pkg : mPackages.values()) {
9077 ApplicationInfo ai = pkg.pkg.applicationInfo;
Kenny Root85387d72010-08-26 10:13:11 -07009078 String dataPath = ai.dataDir;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009079 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
9080
9081 // Avoid any application that has a space in its path
9082 // or that is handled by the system.
9083 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
9084 continue;
9085
9086 // we store on each line the following information for now:
9087 //
9088 // pkgName - package name
9089 // userId - application-specific user id
9090 // debugFlag - 0 or 1 if the package is debuggable.
9091 // dataPath - path to package's data path
9092 //
9093 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
9094 //
9095 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
9096 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
9097 // system/core/run-as/run-as.c
9098 //
9099 sb.setLength(0);
9100 sb.append(ai.packageName);
9101 sb.append(" ");
Jason parksa3cdaa52011-01-13 14:15:43 -06009102 sb.append((int)ai.uid);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009103 sb.append(isDebug ? " 1 " : " 0 ");
9104 sb.append(dataPath);
9105 sb.append("\n");
9106 str.write(sb.toString().getBytes());
9107 }
9108 str.flush();
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07009109 FileUtils.sync(fstr);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009110 str.close();
9111 journal.commit();
9112 }
9113 catch (Exception e) {
9114 journal.rollback();
9115 }
9116
9117 FileUtils.setPermissions(mPackageListFilename.toString(),
9118 FileUtils.S_IRUSR|FileUtils.S_IWUSR
9119 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
9120 |FileUtils.S_IROTH,
9121 -1, -1);
9122
Dianne Hackborne7f97212011-02-24 14:40:20 -08009123 writeStoppedLP();
9124
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07009125 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009126
9127 } catch(XmlPullParserException e) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08009128 Log.wtf(TAG, "Unable to write package manager settings, "
9129 + "current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009130 } catch(java.io.IOException e) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08009131 Log.wtf(TAG, "Unable to write package manager settings, "
9132 + "current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009133 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08009134 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07009135 if (mSettingsFilename.exists()) {
9136 if (!mSettingsFilename.delete()) {
Dianne Hackborne7f97212011-02-24 14:40:20 -08009137 Log.wtf(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07009138 }
9139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009140 //Debug.stopMethodTracing();
9141 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009142
9143 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009144 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009145 serializer.startTag(null, "updated-package");
9146 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009147 if (pkg.realName != null) {
9148 serializer.attribute(null, "realName", pkg.realName);
9149 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009150 serializer.attribute(null, "codePath", pkg.codePathString);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009151 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
9152 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
9153 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009154 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
9156 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
9157 }
Kenny Root85387d72010-08-26 10:13:11 -07009158 if (pkg.nativeLibraryPathString != null) {
9159 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
9160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009161 if (pkg.sharedUser == null) {
9162 serializer.attribute(null, "userId",
9163 Integer.toString(pkg.userId));
9164 } else {
9165 serializer.attribute(null, "sharedUserId",
9166 Integer.toString(pkg.userId));
9167 }
9168 serializer.startTag(null, "perms");
9169 if (pkg.sharedUser == null) {
9170 // If this is a shared user, the permissions will
9171 // be written there. We still need to write an
9172 // empty permissions list so permissionsFixed will
9173 // be set.
9174 for (final String name : pkg.grantedPermissions) {
9175 BasePermission bp = mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009176 if (bp != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009177 // We only need to write signature or system permissions but this wont
9178 // match the semantics of grantedPermissions. So write all permissions.
9179 serializer.startTag(null, "item");
9180 serializer.attribute(null, "name", name);
9181 serializer.endTag(null, "item");
9182 }
9183 }
9184 }
9185 serializer.endTag(null, "perms");
9186 serializer.endTag(null, "updated-package");
9187 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009188
9189 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009190 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009191 serializer.startTag(null, "package");
9192 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009193 if (pkg.realName != null) {
9194 serializer.attribute(null, "realName", pkg.realName);
9195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009196 serializer.attribute(null, "codePath", pkg.codePathString);
9197 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
9198 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
9199 }
Kenny Root85387d72010-08-26 10:13:11 -07009200 if (pkg.nativeLibraryPathString != null) {
9201 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
9202 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009203 serializer.attribute(null, "flags",
9204 Integer.toString(pkg.pkgFlags));
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009205 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
9206 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
9207 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009208 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209 if (pkg.sharedUser == null) {
9210 serializer.attribute(null, "userId",
9211 Integer.toString(pkg.userId));
9212 } else {
9213 serializer.attribute(null, "sharedUserId",
9214 Integer.toString(pkg.userId));
9215 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009216 if (pkg.uidError) {
9217 serializer.attribute(null, "uidError", "true");
9218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009219 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
9220 serializer.attribute(null, "enabled",
9221 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
9222 ? "true" : "false");
9223 }
9224 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
9225 serializer.attribute(null, "installStatus", "false");
9226 }
Jacek Surazski65e13172009-04-28 15:26:38 +02009227 if (pkg.installerPackageName != null) {
9228 serializer.attribute(null, "installer", pkg.installerPackageName);
9229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009230 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
9231 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
9232 serializer.startTag(null, "perms");
9233 if (pkg.sharedUser == null) {
9234 // If this is a shared user, the permissions will
9235 // be written there. We still need to write an
9236 // empty permissions list so permissionsFixed will
9237 // be set.
9238 for (final String name : pkg.grantedPermissions) {
9239 serializer.startTag(null, "item");
9240 serializer.attribute(null, "name", name);
9241 serializer.endTag(null, "item");
9242 }
9243 }
9244 serializer.endTag(null, "perms");
9245 }
9246 if (pkg.disabledComponents.size() > 0) {
9247 serializer.startTag(null, "disabled-components");
9248 for (final String name : pkg.disabledComponents) {
9249 serializer.startTag(null, "item");
9250 serializer.attribute(null, "name", name);
9251 serializer.endTag(null, "item");
9252 }
9253 serializer.endTag(null, "disabled-components");
9254 }
9255 if (pkg.enabledComponents.size() > 0) {
9256 serializer.startTag(null, "enabled-components");
9257 for (final String name : pkg.enabledComponents) {
9258 serializer.startTag(null, "item");
9259 serializer.attribute(null, "name", name);
9260 serializer.endTag(null, "item");
9261 }
9262 serializer.endTag(null, "enabled-components");
9263 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009265 serializer.endTag(null, "package");
9266 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268 void writePermission(XmlSerializer serializer, BasePermission bp)
9269 throws XmlPullParserException, java.io.IOException {
9270 if (bp.type != BasePermission.TYPE_BUILTIN
9271 && bp.sourcePackage != null) {
9272 serializer.startTag(null, "item");
9273 serializer.attribute(null, "name", bp.name);
9274 serializer.attribute(null, "package", bp.sourcePackage);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009275 if (bp.protectionLevel !=
9276 PermissionInfo.PROTECTION_NORMAL) {
9277 serializer.attribute(null, "protection",
9278 Integer.toString(bp.protectionLevel));
9279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009280 if (DEBUG_SETTINGS) Log.v(TAG,
9281 "Writing perm: name=" + bp.name + " type=" + bp.type);
9282 if (bp.type == BasePermission.TYPE_DYNAMIC) {
9283 PermissionInfo pi = bp.perm != null ? bp.perm.info
9284 : bp.pendingInfo;
9285 if (pi != null) {
9286 serializer.attribute(null, "type", "dynamic");
9287 if (pi.icon != 0) {
9288 serializer.attribute(null, "icon",
9289 Integer.toString(pi.icon));
9290 }
9291 if (pi.nonLocalizedLabel != null) {
9292 serializer.attribute(null, "label",
9293 pi.nonLocalizedLabel.toString());
9294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009295 }
9296 }
9297 serializer.endTag(null, "item");
9298 }
9299 }
9300
9301 String getReadMessagesLP() {
9302 return mReadMessages.toString();
9303 }
9304
Oscar Montemayora8529f62009-11-18 10:14:20 -08009305 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009306 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
9307 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08009308 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 while(its.hasNext()) {
9310 String key = its.next();
9311 PackageSetting ps = mPackages.get(key);
9312 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08009313 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 }
9315 }
9316 return ret;
9317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009319 boolean readLP() {
9320 FileInputStream str = null;
9321 if (mBackupSettingsFilename.exists()) {
9322 try {
9323 str = new FileInputStream(mBackupSettingsFilename);
9324 mReadMessages.append("Reading from backup settings file\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07009325 reportSettingsProblem(Log.INFO, "Need to read from backup settings file");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07009326 if (mSettingsFilename.exists()) {
9327 // If both the backup and settings file exist, we
9328 // ignore the settings since it might have been
9329 // corrupted.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009330 Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename);
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07009331 mSettingsFilename.delete();
9332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009333 } catch (java.io.IOException e) {
9334 // We'll try for the normal settings file.
9335 }
9336 }
9337
9338 mPastSignatures.clear();
9339
9340 try {
9341 if (str == null) {
9342 if (!mSettingsFilename.exists()) {
9343 mReadMessages.append("No settings file found\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07009344 reportSettingsProblem(Log.INFO, "No settings file; creating initial state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 return false;
9346 }
9347 str = new FileInputStream(mSettingsFilename);
9348 }
9349 XmlPullParser parser = Xml.newPullParser();
9350 parser.setInput(str, null);
9351
9352 int type;
9353 while ((type=parser.next()) != XmlPullParser.START_TAG
9354 && type != XmlPullParser.END_DOCUMENT) {
9355 ;
9356 }
9357
9358 if (type != XmlPullParser.START_TAG) {
9359 mReadMessages.append("No start tag found in settings file\n");
Dianne Hackbornefb58102010-10-14 16:47:34 -07009360 reportSettingsProblem(Log.WARN, "No start tag found in package manager settings");
Dianne Hackborne7f97212011-02-24 14:40:20 -08009361 Log.wtf(TAG, "No start tag found in package manager settings");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009362 return false;
9363 }
9364
9365 int outerDepth = parser.getDepth();
9366 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9367 && (type != XmlPullParser.END_TAG
9368 || parser.getDepth() > outerDepth)) {
9369 if (type == XmlPullParser.END_TAG
9370 || type == XmlPullParser.TEXT) {
9371 continue;
9372 }
9373
9374 String tagName = parser.getName();
9375 if (tagName.equals("package")) {
9376 readPackageLP(parser);
9377 } else if (tagName.equals("permissions")) {
9378 readPermissionsLP(mPermissions, parser);
9379 } else if (tagName.equals("permission-trees")) {
9380 readPermissionsLP(mPermissionTrees, parser);
9381 } else if (tagName.equals("shared-user")) {
9382 readSharedUserLP(parser);
9383 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08009384 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009385 } else if (tagName.equals("preferred-activities")) {
9386 readPreferredActivitiesLP(parser);
9387 } else if(tagName.equals("updated-package")) {
9388 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009389 } else if (tagName.equals("cleaning-package")) {
9390 String name = parser.getAttributeValue(null, "name");
9391 if (name != null) {
9392 mPackagesToBeCleaned.add(name);
9393 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009394 } else if (tagName.equals("renamed-package")) {
9395 String nname = parser.getAttributeValue(null, "new");
9396 String oname = parser.getAttributeValue(null, "old");
9397 if (nname != null && oname != null) {
9398 mRenamedPackages.put(nname, oname);
9399 }
Dianne Hackbornf22221f2010-04-05 18:35:42 -07009400 } else if (tagName.equals("last-platform-version")) {
9401 mInternalSdkPlatform = mExternalSdkPlatform = 0;
9402 try {
9403 String internal = parser.getAttributeValue(null, "internal");
9404 if (internal != null) {
9405 mInternalSdkPlatform = Integer.parseInt(internal);
9406 }
9407 String external = parser.getAttributeValue(null, "external");
9408 if (external != null) {
Bryan Mawhinney2131a3c2010-04-23 14:38:31 +01009409 mExternalSdkPlatform = Integer.parseInt(external);
Dianne Hackbornf22221f2010-04-05 18:35:42 -07009410 }
9411 } catch (NumberFormatException e) {
9412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009413 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009414 Slog.w(TAG, "Unknown element under <packages>: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009415 + parser.getName());
9416 XmlUtils.skipCurrentTag(parser);
9417 }
9418 }
9419
9420 str.close();
9421
9422 } catch(XmlPullParserException e) {
9423 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackbornefb58102010-10-14 16:47:34 -07009424 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009425 Log.wtf(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009426
9427 } catch(java.io.IOException e) {
9428 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackbornefb58102010-10-14 16:47:34 -07009429 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Dianne Hackborne7f97212011-02-24 14:40:20 -08009430 Log.wtf(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431
9432 }
9433
9434 int N = mPendingPackages.size();
9435 for (int i=0; i<N; i++) {
9436 final PendingPackage pp = mPendingPackages.get(i);
9437 Object idObj = getUserIdLP(pp.sharedId);
9438 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009439 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
Kenny Root806cc132010-09-12 08:34:19 -07009440 (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
9441 pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 if (p == null) {
Dianne Hackbornefb58102010-10-14 16:47:34 -07009443 reportSettingsProblem(Log.WARN, "Unable to create application package for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009444 + pp.name);
9445 continue;
9446 }
9447 p.copyFrom(pp);
9448 } else if (idObj != null) {
9449 String msg = "Bad package setting: package " + pp.name
9450 + " has shared uid " + pp.sharedId
9451 + " that is not a shared uid\n";
9452 mReadMessages.append(msg);
Dianne Hackbornefb58102010-10-14 16:47:34 -07009453 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 } else {
9455 String msg = "Bad package setting: package " + pp.name
9456 + " has shared uid " + pp.sharedId
9457 + " that is not defined\n";
9458 mReadMessages.append(msg);
Dianne Hackbornefb58102010-10-14 16:47:34 -07009459 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 }
9461 }
9462 mPendingPackages.clear();
9463
Dianne Hackborne7f97212011-02-24 14:40:20 -08009464 readStoppedLP();
9465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009466 mReadMessages.append("Read completed successfully: "
9467 + mPackages.size() + " packages, "
9468 + mSharedUsers.size() + " shared uids\n");
9469
9470 return true;
9471 }
9472
9473 private int readInt(XmlPullParser parser, String ns, String name,
9474 int defValue) {
9475 String v = parser.getAttributeValue(ns, name);
9476 try {
9477 if (v == null) {
9478 return defValue;
9479 }
9480 return Integer.parseInt(v);
9481 } catch (NumberFormatException e) {
9482 reportSettingsProblem(Log.WARN,
9483 "Error in package manager settings: attribute " +
9484 name + " has bad integer value " + v + " at "
9485 + parser.getPositionDescription());
9486 }
9487 return defValue;
9488 }
9489
9490 private void readPermissionsLP(HashMap<String, BasePermission> out,
9491 XmlPullParser parser)
9492 throws IOException, XmlPullParserException {
9493 int outerDepth = parser.getDepth();
9494 int type;
9495 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9496 && (type != XmlPullParser.END_TAG
9497 || parser.getDepth() > outerDepth)) {
9498 if (type == XmlPullParser.END_TAG
9499 || type == XmlPullParser.TEXT) {
9500 continue;
9501 }
9502
9503 String tagName = parser.getName();
9504 if (tagName.equals("item")) {
9505 String name = parser.getAttributeValue(null, "name");
9506 String sourcePackage = parser.getAttributeValue(null, "package");
9507 String ptype = parser.getAttributeValue(null, "type");
9508 if (name != null && sourcePackage != null) {
9509 boolean dynamic = "dynamic".equals(ptype);
9510 BasePermission bp = new BasePermission(name, sourcePackage,
9511 dynamic
9512 ? BasePermission.TYPE_DYNAMIC
9513 : BasePermission.TYPE_NORMAL);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009514 bp.protectionLevel = readInt(parser, null, "protection",
9515 PermissionInfo.PROTECTION_NORMAL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009516 if (dynamic) {
9517 PermissionInfo pi = new PermissionInfo();
9518 pi.packageName = sourcePackage.intern();
9519 pi.name = name.intern();
9520 pi.icon = readInt(parser, null, "icon", 0);
9521 pi.nonLocalizedLabel = parser.getAttributeValue(
9522 null, "label");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009523 pi.protectionLevel = bp.protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524 bp.pendingInfo = pi;
9525 }
9526 out.put(bp.name, bp);
9527 } else {
9528 reportSettingsProblem(Log.WARN,
9529 "Error in package manager settings: permissions has"
9530 + " no name at " + parser.getPositionDescription());
9531 }
9532 } else {
9533 reportSettingsProblem(Log.WARN,
9534 "Unknown element reading permissions: "
9535 + parser.getName() + " at "
9536 + parser.getPositionDescription());
9537 }
9538 XmlUtils.skipCurrentTag(parser);
9539 }
9540 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009542 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009543 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009544 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009545 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009546 String codePathStr = parser.getAttributeValue(null, "codePath");
9547 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Kenny Root806cc132010-09-12 08:34:19 -07009548 String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009549 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009550 resourcePathStr = codePathStr;
9551 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009552 String version = parser.getAttributeValue(null, "version");
9553 int versionCode = 0;
9554 if (version != null) {
9555 try {
9556 versionCode = Integer.parseInt(version);
9557 } catch (NumberFormatException e) {
9558 }
9559 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561 int pkgFlags = 0;
9562 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Kenny Root806cc132010-09-12 08:34:19 -07009563 PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
9564 new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009565 String timeStampStr = parser.getAttributeValue(null, "ft");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009566 if (timeStampStr != null) {
9567 try {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009568 long timeStamp = Long.parseLong(timeStampStr, 16);
Kenny Root7d794fb2010-09-13 16:29:49 -07009569 ps.setTimeStamp(timeStamp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 } catch (NumberFormatException e) {
9571 }
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009572 } else {
9573 timeStampStr = parser.getAttributeValue(null, "ts");
9574 if (timeStampStr != null) {
9575 try {
9576 long timeStamp = Long.parseLong(timeStampStr);
9577 ps.setTimeStamp(timeStamp);
9578 } catch (NumberFormatException e) {
9579 }
9580 }
9581 }
9582 timeStampStr = parser.getAttributeValue(null, "it");
9583 if (timeStampStr != null) {
9584 try {
9585 ps.firstInstallTime = Long.parseLong(timeStampStr, 16);
9586 } catch (NumberFormatException e) {
9587 }
9588 }
9589 timeStampStr = parser.getAttributeValue(null, "ut");
9590 if (timeStampStr != null) {
9591 try {
9592 ps.lastUpdateTime = Long.parseLong(timeStampStr, 16);
9593 } catch (NumberFormatException e) {
9594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009595 }
9596 String idStr = parser.getAttributeValue(null, "userId");
9597 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
9598 if(ps.userId <= 0) {
9599 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
9600 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
9601 }
9602 int outerDepth = parser.getDepth();
9603 int type;
9604 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9605 && (type != XmlPullParser.END_TAG
9606 || parser.getDepth() > outerDepth)) {
9607 if (type == XmlPullParser.END_TAG
9608 || type == XmlPullParser.TEXT) {
9609 continue;
9610 }
9611
9612 String tagName = parser.getName();
9613 if (tagName.equals("perms")) {
9614 readGrantedPermissionsLP(parser,
9615 ps.grantedPermissions);
9616 } else {
9617 reportSettingsProblem(Log.WARN,
9618 "Unknown element under <updated-package>: "
9619 + parser.getName());
9620 XmlUtils.skipCurrentTag(parser);
9621 }
9622 }
9623 mDisabledSysPackages.put(name, ps);
9624 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 private void readPackageLP(XmlPullParser parser)
9627 throws XmlPullParserException, IOException {
9628 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009629 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 String idStr = null;
9631 String sharedIdStr = null;
9632 String codePathStr = null;
9633 String resourcePathStr = null;
Kenny Root85387d72010-08-26 10:13:11 -07009634 String nativeLibraryPathStr = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02009636 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009637 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009638 int pkgFlags = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 long timeStamp = 0;
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009640 long firstInstallTime = 0;
9641 long lastUpdateTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009643 String version = null;
9644 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 try {
9646 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009647 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009648 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009649 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009650 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
9651 codePathStr = parser.getAttributeValue(null, "codePath");
9652 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Kenny Root85387d72010-08-26 10:13:11 -07009653 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07009654 version = parser.getAttributeValue(null, "version");
9655 if (version != null) {
9656 try {
9657 versionCode = Integer.parseInt(version);
9658 } catch (NumberFormatException e) {
9659 }
9660 }
Jacek Surazski65e13172009-04-28 15:26:38 +02009661 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009662
9663 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009664 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009665 try {
9666 pkgFlags = Integer.parseInt(systemStr);
9667 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668 }
9669 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009670 // For backward compatibility
9671 systemStr = parser.getAttributeValue(null, "system");
9672 if (systemStr != null) {
9673 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
9674 } else {
9675 // Old settings that don't specify system... just treat
9676 // them as system, good enough.
9677 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
9678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009679 }
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009680 String timeStampStr = parser.getAttributeValue(null, "ft");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 if (timeStampStr != null) {
9682 try {
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009683 timeStamp = Long.parseLong(timeStampStr, 16);
9684 } catch (NumberFormatException e) {
9685 }
9686 } else {
9687 timeStampStr = parser.getAttributeValue(null, "ts");
9688 if (timeStampStr != null) {
9689 try {
9690 timeStamp = Long.parseLong(timeStampStr);
9691 } catch (NumberFormatException e) {
9692 }
9693 }
9694 }
9695 timeStampStr = parser.getAttributeValue(null, "it");
9696 if (timeStampStr != null) {
9697 try {
9698 firstInstallTime = Long.parseLong(timeStampStr, 16);
9699 } catch (NumberFormatException e) {
9700 }
9701 }
9702 timeStampStr = parser.getAttributeValue(null, "ut");
9703 if (timeStampStr != null) {
9704 try {
9705 lastUpdateTime = Long.parseLong(timeStampStr, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009706 } catch (NumberFormatException e) {
9707 }
9708 }
9709 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
9710 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
9711 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
9712 if (resourcePathStr == null) {
9713 resourcePathStr = codePathStr;
9714 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009715 if (realName != null) {
9716 realName = realName.intern();
9717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009718 if (name == null) {
9719 reportSettingsProblem(Log.WARN,
9720 "Error in package manager settings: <package> has no name at "
9721 + parser.getPositionDescription());
9722 } else if (codePathStr == null) {
9723 reportSettingsProblem(Log.WARN,
9724 "Error in package manager settings: <package> has no codePath at "
9725 + parser.getPositionDescription());
9726 } else if (userId > 0) {
Kenny Root806cc132010-09-12 08:34:19 -07009727 packageSetting = addPackageLP(name.intern(), realName, new File(codePathStr),
9728 new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode,
9729 pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
9731 + ": userId=" + userId + " pkg=" + packageSetting);
9732 if (packageSetting == null) {
9733 reportSettingsProblem(Log.ERROR,
9734 "Failure adding uid " + userId
9735 + " while parsing settings at "
9736 + parser.getPositionDescription());
9737 } else {
Kenny Root7d794fb2010-09-13 16:29:49 -07009738 packageSetting.setTimeStamp(timeStamp);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009739 packageSetting.firstInstallTime = firstInstallTime;
9740 packageSetting.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 }
9742 } else if (sharedIdStr != null) {
9743 userId = sharedIdStr != null
9744 ? Integer.parseInt(sharedIdStr) : 0;
9745 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009746 packageSetting = new PendingPackage(name.intern(), realName,
9747 new File(codePathStr), new File(resourcePathStr),
Kenny Root806cc132010-09-12 08:34:19 -07009748 nativeLibraryPathStr, userId, versionCode, pkgFlags);
Kenny Root7d794fb2010-09-13 16:29:49 -07009749 packageSetting.setTimeStamp(timeStamp);
Dianne Hackborn78d6883692010-10-07 01:12:46 -07009750 packageSetting.firstInstallTime = firstInstallTime;
9751 packageSetting.lastUpdateTime = lastUpdateTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752 mPendingPackages.add((PendingPackage) packageSetting);
9753 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
9754 + ": sharedUserId=" + userId + " pkg="
9755 + packageSetting);
9756 } else {
9757 reportSettingsProblem(Log.WARN,
9758 "Error in package manager settings: package "
9759 + name + " has bad sharedId " + sharedIdStr
9760 + " at " + parser.getPositionDescription());
9761 }
9762 } else {
9763 reportSettingsProblem(Log.WARN,
9764 "Error in package manager settings: package "
9765 + name + " has bad userId " + idStr + " at "
9766 + parser.getPositionDescription());
9767 }
9768 } catch (NumberFormatException e) {
9769 reportSettingsProblem(Log.WARN,
9770 "Error in package manager settings: package "
9771 + name + " has bad userId " + idStr + " at "
9772 + parser.getPositionDescription());
9773 }
9774 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08009775 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02009776 packageSetting.installerPackageName = installerPackageName;
Kenny Root85387d72010-08-26 10:13:11 -07009777 packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009778 final String enabledStr = parser.getAttributeValue(null, "enabled");
9779 if (enabledStr != null) {
9780 if (enabledStr.equalsIgnoreCase("true")) {
9781 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
9782 } else if (enabledStr.equalsIgnoreCase("false")) {
9783 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
9784 } else if (enabledStr.equalsIgnoreCase("default")) {
9785 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9786 } else {
9787 reportSettingsProblem(Log.WARN,
9788 "Error in package manager settings: package "
9789 + name + " has bad enabled value: " + idStr
9790 + " at " + parser.getPositionDescription());
9791 }
9792 } else {
9793 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9794 }
9795 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
9796 if (installStatusStr != null) {
9797 if (installStatusStr.equalsIgnoreCase("false")) {
9798 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
9799 } else {
9800 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
9801 }
9802 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009804 int outerDepth = parser.getDepth();
9805 int type;
9806 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9807 && (type != XmlPullParser.END_TAG
9808 || parser.getDepth() > outerDepth)) {
9809 if (type == XmlPullParser.END_TAG
9810 || type == XmlPullParser.TEXT) {
9811 continue;
9812 }
9813
9814 String tagName = parser.getName();
9815 if (tagName.equals("disabled-components")) {
9816 readDisabledComponentsLP(packageSetting, parser);
9817 } else if (tagName.equals("enabled-components")) {
9818 readEnabledComponentsLP(packageSetting, parser);
9819 } else if (tagName.equals("sigs")) {
9820 packageSetting.signatures.readXml(parser, mPastSignatures);
9821 } else if (tagName.equals("perms")) {
9822 readGrantedPermissionsLP(parser,
Dianne Hackbornf657b632010-03-22 18:08:07 -07009823 packageSetting.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009824 packageSetting.permissionsFixed = true;
9825 } else {
9826 reportSettingsProblem(Log.WARN,
9827 "Unknown element under <package>: "
9828 + parser.getName());
9829 XmlUtils.skipCurrentTag(parser);
9830 }
9831 }
9832 } else {
9833 XmlUtils.skipCurrentTag(parser);
9834 }
9835 }
9836
9837 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
9838 XmlPullParser parser)
9839 throws IOException, XmlPullParserException {
9840 int outerDepth = parser.getDepth();
9841 int type;
9842 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9843 && (type != XmlPullParser.END_TAG
9844 || parser.getDepth() > outerDepth)) {
9845 if (type == XmlPullParser.END_TAG
9846 || type == XmlPullParser.TEXT) {
9847 continue;
9848 }
9849
9850 String tagName = parser.getName();
9851 if (tagName.equals("item")) {
9852 String name = parser.getAttributeValue(null, "name");
9853 if (name != null) {
9854 packageSetting.disabledComponents.add(name.intern());
9855 } else {
9856 reportSettingsProblem(Log.WARN,
9857 "Error in package manager settings: <disabled-components> has"
9858 + " no name at " + parser.getPositionDescription());
9859 }
9860 } else {
9861 reportSettingsProblem(Log.WARN,
9862 "Unknown element under <disabled-components>: "
9863 + parser.getName());
9864 }
9865 XmlUtils.skipCurrentTag(parser);
9866 }
9867 }
9868
9869 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
9870 XmlPullParser parser)
9871 throws IOException, XmlPullParserException {
9872 int outerDepth = parser.getDepth();
9873 int type;
9874 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9875 && (type != XmlPullParser.END_TAG
9876 || parser.getDepth() > outerDepth)) {
9877 if (type == XmlPullParser.END_TAG
9878 || type == XmlPullParser.TEXT) {
9879 continue;
9880 }
9881
9882 String tagName = parser.getName();
9883 if (tagName.equals("item")) {
9884 String name = parser.getAttributeValue(null, "name");
9885 if (name != null) {
9886 packageSetting.enabledComponents.add(name.intern());
9887 } else {
9888 reportSettingsProblem(Log.WARN,
9889 "Error in package manager settings: <enabled-components> has"
9890 + " no name at " + parser.getPositionDescription());
9891 }
9892 } else {
9893 reportSettingsProblem(Log.WARN,
9894 "Unknown element under <enabled-components>: "
9895 + parser.getName());
9896 }
9897 XmlUtils.skipCurrentTag(parser);
9898 }
9899 }
9900
9901 private void readSharedUserLP(XmlPullParser parser)
9902 throws XmlPullParserException, IOException {
9903 String name = null;
9904 String idStr = null;
9905 int pkgFlags = 0;
9906 SharedUserSetting su = null;
9907 try {
9908 name = parser.getAttributeValue(null, "name");
9909 idStr = parser.getAttributeValue(null, "userId");
9910 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
9911 if ("true".equals(parser.getAttributeValue(null, "system"))) {
9912 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
9913 }
9914 if (name == null) {
9915 reportSettingsProblem(Log.WARN,
9916 "Error in package manager settings: <shared-user> has no name at "
9917 + parser.getPositionDescription());
9918 } else if (userId == 0) {
9919 reportSettingsProblem(Log.WARN,
9920 "Error in package manager settings: shared-user "
9921 + name + " has bad userId " + idStr + " at "
9922 + parser.getPositionDescription());
9923 } else {
9924 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
9925 reportSettingsProblem(Log.ERROR,
9926 "Occurred while parsing settings at "
9927 + parser.getPositionDescription());
9928 }
9929 }
9930 } catch (NumberFormatException e) {
9931 reportSettingsProblem(Log.WARN,
9932 "Error in package manager settings: package "
9933 + name + " has bad userId " + idStr + " at "
9934 + parser.getPositionDescription());
9935 };
9936
9937 if (su != null) {
9938 int outerDepth = parser.getDepth();
9939 int type;
9940 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9941 && (type != XmlPullParser.END_TAG
9942 || parser.getDepth() > outerDepth)) {
9943 if (type == XmlPullParser.END_TAG
9944 || type == XmlPullParser.TEXT) {
9945 continue;
9946 }
9947
9948 String tagName = parser.getName();
9949 if (tagName.equals("sigs")) {
9950 su.signatures.readXml(parser, mPastSignatures);
9951 } else if (tagName.equals("perms")) {
Dianne Hackbornf657b632010-03-22 18:08:07 -07009952 readGrantedPermissionsLP(parser, su.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009953 } else {
9954 reportSettingsProblem(Log.WARN,
9955 "Unknown element under <shared-user>: "
9956 + parser.getName());
9957 XmlUtils.skipCurrentTag(parser);
9958 }
9959 }
9960
9961 } else {
9962 XmlUtils.skipCurrentTag(parser);
9963 }
9964 }
9965
9966 private void readGrantedPermissionsLP(XmlPullParser parser,
9967 HashSet<String> outPerms) throws IOException, XmlPullParserException {
9968 int outerDepth = parser.getDepth();
9969 int type;
9970 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9971 && (type != XmlPullParser.END_TAG
9972 || parser.getDepth() > outerDepth)) {
9973 if (type == XmlPullParser.END_TAG
9974 || type == XmlPullParser.TEXT) {
9975 continue;
9976 }
9977
9978 String tagName = parser.getName();
9979 if (tagName.equals("item")) {
9980 String name = parser.getAttributeValue(null, "name");
9981 if (name != null) {
9982 outPerms.add(name.intern());
9983 } else {
9984 reportSettingsProblem(Log.WARN,
9985 "Error in package manager settings: <perms> has"
9986 + " no name at " + parser.getPositionDescription());
9987 }
9988 } else {
9989 reportSettingsProblem(Log.WARN,
9990 "Unknown element under <perms>: "
9991 + parser.getName());
9992 }
9993 XmlUtils.skipCurrentTag(parser);
9994 }
9995 }
9996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009997 private void readPreferredActivitiesLP(XmlPullParser parser)
9998 throws XmlPullParserException, IOException {
9999 int outerDepth = parser.getDepth();
10000 int type;
10001 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
10002 && (type != XmlPullParser.END_TAG
10003 || parser.getDepth() > outerDepth)) {
10004 if (type == XmlPullParser.END_TAG
10005 || type == XmlPullParser.TEXT) {
10006 continue;
10007 }
10008
10009 String tagName = parser.getName();
10010 if (tagName.equals("item")) {
10011 PreferredActivity pa = new PreferredActivity(parser);
10012 if (pa.mParseError == null) {
10013 mPreferredActivities.addFilter(pa);
10014 } else {
10015 reportSettingsProblem(Log.WARN,
10016 "Error in package manager settings: <preferred-activity> "
10017 + pa.mParseError + " at "
10018 + parser.getPositionDescription());
10019 }
10020 } else {
10021 reportSettingsProblem(Log.WARN,
10022 "Unknown element under <preferred-activities>: "
10023 + parser.getName());
10024 XmlUtils.skipCurrentTag(parser);
10025 }
10026 }
10027 }
10028
10029 // Returns -1 if we could not find an available UserId to assign
10030 private int newUserIdLP(Object obj) {
10031 // Let's be stupidly inefficient for now...
10032 final int N = mUserIds.size();
10033 for (int i=0; i<N; i++) {
10034 if (mUserIds.get(i) == null) {
10035 mUserIds.set(i, obj);
10036 return FIRST_APPLICATION_UID + i;
10037 }
10038 }
10039
10040 // None left?
10041 if (N >= MAX_APPLICATION_UIDS) {
10042 return -1;
10043 }
10044
10045 mUserIds.add(obj);
10046 return FIRST_APPLICATION_UID + N;
10047 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 public PackageSetting getDisabledSystemPkg(String name) {
10050 synchronized(mPackages) {
10051 PackageSetting ps = mDisabledSysPackages.get(name);
10052 return ps;
10053 }
10054 }
10055
10056 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
Dianne Hackborn46730fc2010-07-24 16:32:42 -070010057 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
10058 return true;
10059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010060 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
10061 if (Config.LOGV) {
10062 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
10063 + " componentName = " + componentInfo.name);
10064 Log.v(TAG, "enabledComponents: "
10065 + Arrays.toString(packageSettings.enabledComponents.toArray()));
10066 Log.v(TAG, "disabledComponents: "
10067 + Arrays.toString(packageSettings.disabledComponents.toArray()));
10068 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -080010069 if (packageSettings == null) {
10070 if (false) {
10071 Log.w(TAG, "WAITING FOR DEBUGGER");
10072 Debug.waitForDebugger();
10073 Log.i(TAG, "We will crash!");
10074 }
Dianne Hackborn46730fc2010-07-24 16:32:42 -070010075 return false;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -080010076 }
Dianne Hackborn46730fc2010-07-24 16:32:42 -070010077 if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
10078 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
10079 && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
10080 return false;
10081 }
10082 if (packageSettings.enabledComponents.contains(componentInfo.name)) {
10083 return true;
10084 }
10085 if (packageSettings.disabledComponents.contains(componentInfo.name)) {
10086 return false;
10087 }
10088 return componentInfo.enabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010089 }
10090 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010091
10092 // ------- apps on sdcard specific code -------
10093 static final boolean DEBUG_SD_INSTALL = false;
Kenny Root305bcbf2010-09-03 07:56:38 -070010094 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD";
10095 private static final String SD_ENCRYPTION_ALGORITHM = "AES";
10096 static final int MAX_CONTAINERS = 250;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080010097 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010098
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010099 private String getEncryptKey() {
10100 try {
Kenny Root305bcbf2010-09-03 07:56:38 -070010101 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(
10102 SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010103 if (sdEncKey == null) {
Kenny Root305bcbf2010-09-03 07:56:38 -070010104 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128,
10105 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010106 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010107 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010108 return null;
10109 }
10110 }
10111 return sdEncKey;
10112 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010113 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010114 return null;
Rich Cannings8d578832010-09-09 15:12:40 -070010115 } catch (IOException ioe) {
10116 Slog.e(TAG, "Failed to retrieve encryption keys with exception: "
10117 + ioe);
10118 return null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010119 }
Rich Cannings8d578832010-09-09 15:12:40 -070010120
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080010121 }
10122
Kenny Rootc78a8072010-07-27 15:18:38 -070010123 /* package */ static String getTempContainerId() {
10124 int tmpIdx = 1;
10125 String list[] = PackageHelper.getSecureContainerList();
10126 if (list != null) {
10127 for (final String name : list) {
10128 // Ignore null and non-temporary container entries
10129 if (name == null || !name.startsWith(mTempContainerPrefix)) {
10130 continue;
10131 }
10132
10133 String subStr = name.substring(mTempContainerPrefix.length());
10134 try {
10135 int cid = Integer.parseInt(subStr);
10136 if (cid >= tmpIdx) {
10137 tmpIdx = cid + 1;
10138 }
10139 } catch (NumberFormatException e) {
10140 }
10141 }
10142 }
10143 return mTempContainerPrefix + tmpIdx;
10144 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010145
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080010146 /*
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010147 * Update media status on PackageManager.
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080010148 */
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010149 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
Marco Nelissen584f1372010-05-24 16:34:30 -070010150 int callingUid = Binder.getCallingUid();
10151 if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010152 throw new SecurityException("Media status can only be updated by the system");
10153 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -080010154 synchronized (mPackages) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -080010155 Log.i(TAG, "Updating external media status from " +
10156 (mMediaMounted ? "mounted" : "unmounted") + " to " +
10157 (mediaStatus ? "mounted" : "unmounted"));
Dianne Hackborne83cefce2010-02-04 17:38:14 -080010158 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
10159 mediaStatus+", mMediaMounted=" + mMediaMounted);
10160 if (mediaStatus == mMediaMounted) {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010161 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
10162 reportStatus ? 1 : 0, -1);
10163 mHandler.sendMessage(msg);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010164 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010165 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -080010166 mMediaMounted = mediaStatus;
Dianne Hackborne83cefce2010-02-04 17:38:14 -080010167 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010168 // Queue up an async operation since the package installation may take a little while.
10169 mHandler.post(new Runnable() {
10170 public void run() {
10171 mHandler.removeCallbacks(this);
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010172 updateExternalMediaStatusInner(mediaStatus, reportStatus);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010173 }
10174 });
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010175 }
10176
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010177 /*
10178 * Collect information of applications on external media, map them
10179 * against existing containers and update information based on current
10180 * mount status. Please note that we always have to report status
10181 * if reportStatus has been set to true especially when unloading packages.
10182 */
10183 private void updateExternalMediaStatusInner(boolean mediaStatus,
10184 boolean reportStatus) {
10185 // Collection of uids
10186 int uidArr[] = null;
10187 // Collection of stale containers
10188 HashSet<String> removeCids = new HashSet<String>();
10189 // Collection of packages on external media with valid containers.
10190 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
10191 // Get list of secure containers.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -080010192 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010193 if (list == null || list.length == 0) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -080010194 Log.i(TAG, "No secure containers on sdcard");
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010195 } else {
10196 // Process list of secure containers and categorize them
10197 // as active or stale based on their package internal state.
10198 int uidList[] = new int[list.length];
10199 int num = 0;
10200 synchronized (mPackages) {
10201 for (String cid : list) {
10202 SdInstallArgs args = new SdInstallArgs(cid);
10203 if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010204 String pkgName = args.getPackageName();
10205 if (pkgName == null) {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010206 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
10207 removeCids.add(cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010208 continue;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010209 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010210 if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
10211 PackageSetting ps = mSettings.mPackages.get(pkgName);
Suchi Amalapurapu1ace5bc2010-05-13 12:05:53 -070010212 // The package status is changed only if the code path
10213 // matches between settings and the container id.
10214 if (ps != null && ps.codePathString != null &&
10215 ps.codePathString.equals(args.getCodePath())) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010216 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
10217 " corresponds to pkg : " + pkgName +
10218 " at code path: " + ps.codePathString);
10219 // We do have a valid package installed on sdcard
10220 processCids.put(args, ps.codePathString);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010221 int uid = ps.userId;
10222 if (uid != -1) {
10223 uidList[num++] = uid;
10224 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010225 } else {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010226 // Stale container on sdcard. Just delete
10227 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
10228 removeCids.add(cid);
10229 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -080010230 }
10231 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010232
10233 if (num > 0) {
10234 // Sort uid list
10235 Arrays.sort(uidList, 0, num);
10236 // Throw away duplicates
10237 uidArr = new int[num];
10238 uidArr[0] = uidList[0];
10239 int di = 0;
10240 for (int i = 1; i < num; i++) {
10241 if (uidList[i-1] != uidList[i]) {
10242 uidArr[di++] = uidList[i];
10243 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010244 }
10245 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010246 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010247 // Process packages with valid entries.
10248 if (mediaStatus) {
10249 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010250 loadMediaPackages(processCids, uidArr, removeCids);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010251 startCleaningPackages();
10252 } else {
10253 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010254 unloadMediaPackages(processCids, uidArr, reportStatus);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010255 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010256 }
10257
10258 private void sendResourcesChangedBroadcast(boolean mediaStatus,
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010259 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010260 int size = pkgList.size();
10261 if (size > 0) {
10262 // Send broadcasts here
10263 Bundle extras = new Bundle();
10264 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
10265 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010266 if (uidArr != null) {
10267 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
10268 }
10269 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
10270 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Dianne Hackborne7f97212011-02-24 14:40:20 -080010271 sendPackageBroadcast(action, null, extras, null, finishedReceiver);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010272 }
10273 }
10274
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010275 /*
10276 * Look at potentially valid container ids from processCids
10277 * If package information doesn't match the one on record
10278 * or package scanning fails, the cid is added to list of
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010279 * removeCids. We currently don't delete stale containers.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010280 */
10281 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010282 int uidArr[], HashSet<String> removeCids) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010283 ArrayList<String> pkgList = new ArrayList<String>();
10284 Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010285 boolean doGc = false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010286 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010287 String codePath = processCids.get(args);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010288 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : "
10289 + args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010290 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010291 try {
10292 // Make sure there are no container errors first.
10293 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED)
10294 != PackageManager.INSTALL_SUCCEEDED) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010295 Slog.e(TAG, "Failed to mount cid : " + args.cid +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010296 " when installing from sdcard");
10297 continue;
10298 }
10299 // Check code path here.
10300 if (codePath == null || !codePath.equals(args.getCodePath())) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -080010301 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010302 " does not match one in settings " + codePath);
10303 continue;
10304 }
10305 // Parse package
Dianne Hackborn399cccb2010-04-13 22:57:49 -070010306 int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010307 doGc = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010308 synchronized (mInstallLock) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -070010309 final PackageParser.Package pkg = scanPackageLI(new File(codePath),
Dianne Hackborn78d6883692010-10-07 01:12:46 -070010310 parseFlags, 0, 0);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010311 // Scan the package
Suchi Amalapurapuae181712010-03-30 14:01:02 -070010312 if (pkg != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010313 synchronized (mPackages) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010314 retCode = PackageManager.INSTALL_SUCCEEDED;
10315 pkgList.add(pkg.packageName);
10316 // Post process args
10317 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
10318 }
10319 } else {
Suchi Amalapurapuae181712010-03-30 14:01:02 -070010320 Slog.i(TAG, "Failed to install pkg from " +
10321 codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010322 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010323 }
10324
10325 } finally {
10326 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
10327 // Don't destroy container here. Wait till gc clears things up.
10328 removeCids.add(args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010329 }
10330 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010331 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010332 synchronized (mPackages) {
Dianne Hackbornf22221f2010-04-05 18:35:42 -070010333 // If the platform SDK has changed since the last time we booted,
10334 // we need to re-grant app permission to catch any new ones that
10335 // appear. This is really a hack, and means that apps can in some
10336 // cases get permissions that the user didn't initially explicitly
10337 // allow... it would be nice to have some better way to handle
10338 // this situation.
10339 final boolean regrantPermissions = mSettings.mExternalSdkPlatform
10340 != mSdkVersion;
10341 if (regrantPermissions) Slog.i(TAG, "Platform changed from "
10342 + mSettings.mExternalSdkPlatform + " to " + mSdkVersion
10343 + "; regranting permissions for external storage");
10344 mSettings.mExternalSdkPlatform = mSdkVersion;
10345
Dianne Hackbornaf7cea32010-03-24 12:59:52 -070010346 // Make sure group IDs have been assigned, and any permission
10347 // changes in other apps are accounted for
Dianne Hackborn92cfa102010-04-28 11:00:44 -070010348 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -070010349 // Persist settings
10350 mSettings.writeLP();
10351 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -080010352 // Send a broadcast to let everyone know we are done processing
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010353 if (pkgList.size() > 0) {
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010354 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010355 }
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010356 // Force gc to avoid any stale parser references that we might have.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010357 if (doGc) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010358 Runtime.getRuntime().gc();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010359 }
Kenny Rootf369a9b2010-07-28 14:47:01 -070010360 // List stale containers and destroy stale temporary containers.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010361 if (removeCids != null) {
10362 for (String cid : removeCids) {
Kenny Rootf369a9b2010-07-28 14:47:01 -070010363 if (cid.startsWith(mTempContainerPrefix)) {
10364 Log.i(TAG, "Destroying stale temporary container " + cid);
10365 PackageHelper.destroySdDir(cid);
10366 } else {
10367 Log.w(TAG, "Container " + cid + " is stale");
10368 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010369 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010370 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010371 }
10372
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010373 /*
10374 * Utility method to unload a list of specified containers
10375 */
10376 private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
10377 // Just unmount all valid containers.
10378 for (SdInstallArgs arg : cidArgs) {
10379 synchronized (mInstallLock) {
10380 arg.doPostDeleteLI(false);
10381 }
10382 }
10383 }
10384
10385 /*
10386 * Unload packages mounted on external media. This involves deleting
10387 * package data from internal structures, sending broadcasts about
10388 * diabled packages, gc'ing to free up references, unmounting all
10389 * secure containers corresponding to packages on external media, and
10390 * posting a UPDATED_MEDIA_STATUS message if status has been requested.
10391 * Please note that we always have to post this message if status has
10392 * been requested no matter what.
10393 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010394 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010395 int uidArr[], final boolean reportStatus) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010396 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010397 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010398 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010399 final Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010400 for (SdInstallArgs args : keys) {
10401 String cid = args.cid;
10402 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010403 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010404 // Delete package internally
10405 PackageRemovedInfo outInfo = new PackageRemovedInfo();
10406 synchronized (mInstallLock) {
10407 boolean res = deletePackageLI(pkgName, false,
Dianne Hackborn3aeee332010-10-02 18:56:33 -070010408 PackageManager.DONT_DELETE_DATA, outInfo, false);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010409 if (res) {
10410 pkgList.add(pkgName);
10411 } else {
Jeff Brown07330792010-03-30 19:57:08 -070010412 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -080010413 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010414 }
10415 }
10416 }
Dianne Hackborn3aeee332010-10-02 18:56:33 -070010417
10418 synchronized (mPackages) {
10419 // We didn't update the settings after removing each package;
10420 // write them now for all packages.
10421 mSettings.writeLP();
10422 }
10423
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010424 // We have to absolutely send UPDATED_MEDIA_STATUS only
10425 // after confirming that all the receivers processed the ordered
10426 // broadcast when packages get disabled, force a gc to clean things up.
10427 // and unload all the containers.
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010428 if (pkgList.size() > 0) {
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010429 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() {
10430 public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
10431 boolean ordered, boolean sticky) throws RemoteException {
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010432 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
10433 reportStatus ? 1 : 0, 1, keys);
10434 mHandler.sendMessage(msg);
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010435 }
10436 });
Suchi Amalapurapu3d244252010-04-08 14:37:05 -070010437 } else {
10438 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS,
10439 reportStatus ? 1 : 0, -1, keys);
10440 mHandler.sendMessage(msg);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080010441 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -080010442 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010443
10444 public void movePackage(final String packageName,
10445 final IPackageMoveObserver observer, final int flags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010446 mContext.enforceCallingOrSelfPermission(
10447 android.Manifest.permission.MOVE_PACKAGE, null);
10448 int returnCode = PackageManager.MOVE_SUCCEEDED;
10449 int currFlags = 0;
10450 int newFlags = 0;
10451 synchronized (mPackages) {
10452 PackageParser.Package pkg = mPackages.get(packageName);
10453 if (pkg == null) {
10454 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010455 } else {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010456 // Disable moving fwd locked apps and system packages
Kenny Root85387d72010-08-26 10:13:11 -070010457 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010458 Slog.w(TAG, "Cannot move system application");
10459 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
Kenny Root85387d72010-08-26 10:13:11 -070010460 } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010461 Slog.w(TAG, "Cannot move forward locked app.");
10462 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
Kenny Rootdeb11262010-08-02 11:36:21 -070010463 } else if (pkg.mOperationPending) {
10464 Slog.w(TAG, "Attempt to move package which has pending operations");
10465 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010466 } else {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010467 // Find install location first
10468 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
10469 (flags & PackageManager.MOVE_INTERNAL) != 0) {
10470 Slog.w(TAG, "Ambigous flags specified for move location.");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010471 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010472 } else {
10473 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
10474 PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
Kenny Root85387d72010-08-26 10:13:11 -070010475 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
10476 : PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010477 if (newFlags == currFlags) {
10478 Slog.w(TAG, "No move required. Trying to move to same location");
10479 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
10480 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010481 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010482 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10483 pkg.mOperationPending = true;
10484 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010485 }
10486 }
10487 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
Kenny Root85387d72010-08-26 10:13:11 -070010488 processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010489 } else {
10490 Message msg = mHandler.obtainMessage(INIT_COPY);
10491 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
Kenny Root85387d72010-08-26 10:13:11 -070010492 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
10493 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
10494 pkg.applicationInfo.dataDir);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010495 msg.obj = mp;
10496 mHandler.sendMessage(msg);
10497 }
10498 }
10499 }
10500
10501 private void processPendingMove(final MoveParams mp, final int currentStatus) {
10502 // Queue up an async operation since the package deletion may take a little while.
10503 mHandler.post(new Runnable() {
10504 public void run() {
10505 mHandler.removeCallbacks(this);
10506 int returnCode = currentStatus;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010507 if (currentStatus == PackageManager.MOVE_SUCCEEDED) {
10508 int uidArr[] = null;
10509 ArrayList<String> pkgList = null;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010510 synchronized (mPackages) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010511 PackageParser.Package pkg = mPackages.get(mp.packageName);
Kenny Root85387d72010-08-26 10:13:11 -070010512 if (pkg == null) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010513 Slog.w(TAG, " Package " + mp.packageName +
10514 " doesn't exist. Aborting move");
10515 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
10516 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
10517 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
10518 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
10519 " Aborting move and returning error");
10520 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10521 } else {
10522 uidArr = new int[] { pkg.applicationInfo.uid };
10523 pkgList = new ArrayList<String>();
10524 pkgList.add(mp.packageName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010525 }
10526 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010527 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10528 // Send resources unavailable broadcast
Dianne Hackbornecb0e632010-04-07 20:22:55 -070010529 sendResourcesChangedBroadcast(false, pkgList, uidArr, null);
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010530 // Update package code and resource paths
10531 synchronized (mInstallLock) {
10532 synchronized (mPackages) {
10533 PackageParser.Package pkg = mPackages.get(mp.packageName);
10534 // Recheck for package again.
Kenny Root6a6b0072010-10-07 16:46:10 -070010535 if (pkg == null) {
10536 Slog.w(TAG, " Package " + mp.packageName
10537 + " doesn't exist. Aborting move");
10538 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010539 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
10540 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " +
10541 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir +
10542 " Aborting move and returning error");
10543 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
10544 } else {
Kenny Root85387d72010-08-26 10:13:11 -070010545 final String oldCodePath = pkg.mPath;
10546 final String newCodePath = mp.targetArgs.getCodePath();
10547 final String newResPath = mp.targetArgs.getResourcePath();
10548 final String newNativePath = mp.targetArgs.getNativeLibraryPath();
Kenny Root6a6b0072010-10-07 16:46:10 -070010549
10550 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) {
10551 if (mInstaller
10552 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
10553 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10554 } else {
10555 NativeLibraryHelper.copyNativeBinariesLI(
10556 new File(newCodePath), new File(newNativePath));
10557 }
10558 } else {
10559 if (mInstaller.linkNativeLibraryDirectory(
10560 pkg.applicationInfo.dataDir, newNativePath) < 0) {
10561 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10562 }
10563 }
10564
10565 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
10566 pkg.mPath = newCodePath;
10567 // Move dex files around
10568 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) {
10569 // Moving of dex files failed. Set
10570 // error code and abort move.
10571 pkg.mPath = pkg.mScanPath;
10572 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
10573 }
10574 }
10575
10576 if (returnCode == PackageManager.MOVE_SUCCEEDED) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010577 pkg.mScanPath = newCodePath;
10578 pkg.applicationInfo.sourceDir = newCodePath;
10579 pkg.applicationInfo.publicSourceDir = newResPath;
Kenny Root85387d72010-08-26 10:13:11 -070010580 pkg.applicationInfo.nativeLibraryDir = newNativePath;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010581 PackageSetting ps = (PackageSetting) pkg.mExtras;
10582 ps.codePath = new File(pkg.applicationInfo.sourceDir);
10583 ps.codePathString = ps.codePath.getPath();
10584 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
10585 ps.resourcePathString = ps.resourcePath.getPath();
Kenny Root0ac83f52010-08-30 15:12:24 -070010586 ps.nativeLibraryPathString = newNativePath;
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010587 // Set the application info flag correctly.
10588 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
10589 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10590 } else {
10591 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
10592 }
10593 ps.setFlags(pkg.applicationInfo.flags);
10594 mAppDirs.remove(oldCodePath);
10595 mAppDirs.put(newCodePath, pkg);
10596 // Persist settings
10597 mSettings.writeLP();
10598 }
10599 }
10600 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010601 }
Suchi Amalapurapu0c1285f2010-04-14 17:05:48 -070010602 // Send resources available broadcast
10603 sendResourcesChangedBroadcast(true, pkgList, uidArr, null);
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010604 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010605 }
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010606 if (returnCode != PackageManager.MOVE_SUCCEEDED){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010607 // Clean up failed installation
10608 if (mp.targetArgs != null) {
Suchi Amalapurapu30f775b2010-04-06 11:41:23 -070010609 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -080010610 }
10611 } else {
10612 // Force a gc to clear things up.
10613 Runtime.getRuntime().gc();
10614 // Delete older code
10615 synchronized (mInstallLock) {
10616 mp.srcArgs.doPostDeleteLI(true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010617 }
10618 }
Kenny Rootdeb11262010-08-02 11:36:21 -070010619
10620 // Allow more operations on this file if we didn't fail because
10621 // an operation was already pending for this package.
10622 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) {
10623 synchronized (mPackages) {
10624 PackageParser.Package pkg = mPackages.get(mp.packageName);
10625 if (pkg != null) {
10626 pkg.mOperationPending = false;
10627 }
10628 }
10629 }
10630
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080010631 IPackageMoveObserver observer = mp.observer;
10632 if (observer != null) {
10633 try {
10634 observer.packageMoved(mp.packageName, returnCode);
10635 } catch (RemoteException e) {
10636 Log.i(TAG, "Observer no longer exists.");
10637 }
10638 }
10639 }
10640 });
10641 }
Suchi Amalapurapu40e47252010-04-07 16:15:50 -070010642
10643 public boolean setInstallLocation(int loc) {
10644 mContext.enforceCallingOrSelfPermission(
10645 android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
10646 if (getInstallLocation() == loc) {
10647 return true;
10648 }
10649 if (loc == PackageHelper.APP_INSTALL_AUTO ||
10650 loc == PackageHelper.APP_INSTALL_INTERNAL ||
10651 loc == PackageHelper.APP_INSTALL_EXTERNAL) {
10652 android.provider.Settings.System.putInt(mContext.getContentResolver(),
10653 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc);
10654 return true;
10655 }
10656 return false;
10657 }
10658
10659 public int getInstallLocation() {
10660 return android.provider.Settings.System.getInt(mContext.getContentResolver(),
10661 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO);
10662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010663}