blob: 7ce9a4ce69a1157c297a6db1220386a4959de5e8 [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;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080021import com.android.internal.content.PackageHelper;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080022import com.android.internal.util.FastXmlSerializer;
23import com.android.internal.util.XmlUtils;
David 'Digit' Turneradd13762010-02-03 17:34:58 -080024import com.android.server.JournaledFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025
26import org.xmlpull.v1.XmlPullParser;
27import org.xmlpull.v1.XmlPullParserException;
28import org.xmlpull.v1.XmlSerializer;
29
30import android.app.ActivityManagerNative;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080031import android.app.DevicePolicyManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.app.IActivityManager;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080033import android.app.IDevicePolicyManager;
Christopher Tate1bb69062010-02-19 17:02:12 -080034import android.backup.IBackupManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.content.Context;
37import android.content.Intent;
38import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070039import android.content.IntentSender;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080040import android.content.ServiceConnection;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070041import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.ActivityInfo;
43import android.content.pm.ApplicationInfo;
44import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070045import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.content.pm.IPackageDataObserver;
47import android.content.pm.IPackageDeleteObserver;
48import android.content.pm.IPackageInstallObserver;
49import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080050import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.pm.IPackageStatsObserver;
52import android.content.pm.InstrumentationInfo;
53import android.content.pm.PackageInfo;
54import android.content.pm.PackageManager;
55import android.content.pm.PackageStats;
56import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
57import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
58import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.pm.PackageParser;
60import android.content.pm.PermissionInfo;
61import android.content.pm.PermissionGroupInfo;
62import android.content.pm.ProviderInfo;
63import android.content.pm.ResolveInfo;
64import android.content.pm.ServiceInfo;
65import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.net.Uri;
67import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070068import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080070import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080072import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070073import android.os.Looper;
74import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.Parcel;
76import android.os.RemoteException;
77import android.os.Environment;
78import android.os.FileObserver;
79import android.os.FileUtils;
80import android.os.Handler;
San Mehatb1043402010-02-05 08:26:50 -080081import android.os.storage.StorageResultCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.ParcelFileDescriptor;
83import android.os.Process;
84import android.os.ServiceManager;
85import android.os.SystemClock;
86import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080087import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.util.*;
89import android.view.Display;
90import android.view.WindowManager;
91
92import java.io.File;
93import java.io.FileDescriptor;
94import java.io.FileInputStream;
95import java.io.FileNotFoundException;
96import java.io.FileOutputStream;
97import java.io.FileReader;
98import java.io.FilenameFilter;
99import java.io.IOException;
100import java.io.InputStream;
101import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800102import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800103import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import java.util.ArrayList;
105import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700106import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import java.util.Collections;
108import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800109import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import java.util.Enumeration;
111import java.util.HashMap;
112import java.util.HashSet;
113import java.util.Iterator;
114import java.util.List;
115import java.util.Map;
116import java.util.Set;
117import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800118import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import java.util.zip.ZipFile;
120import java.util.zip.ZipOutputStream;
121
122class PackageManagerService extends IPackageManager.Stub {
123 private static final String TAG = "PackageManager";
124 private static final boolean DEBUG_SETTINGS = false;
125 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800126 private static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800127 private static final boolean DEBUG_INSTALL = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
129 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
130 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400131 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final int FIRST_APPLICATION_UID =
133 Process.FIRST_APPLICATION_UID;
134 private static final int MAX_APPLICATION_UIDS = 1000;
135
136 private static final boolean SHOW_INFO = false;
137
138 private static final boolean GET_CERTIFICATES = true;
139
Oscar Montemayora8529f62009-11-18 10:14:20 -0800140 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 private static final int REMOVE_EVENTS =
143 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
144 private static final int ADD_EVENTS =
145 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
146
147 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800148 // Suffix used during package installation when copying/moving
149 // package apks to install directory.
150 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -0800152 /**
153 * Indicates the state of installation. Used by PackageManager to
154 * figure out incomplete installations. Say a package is being installed
155 * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
156 * the package installation is successful or unsuccesful lin which case
157 * the PackageManager will no longer maintain state information associated
158 * with the package. If some exception(like device freeze or battery being
159 * pulled out) occurs during installation of a package, the PackageManager
160 * needs this information to clean up the previously failed installation.
161 */
162 private static final int PKG_INSTALL_INCOMPLETE = 0;
163 private static final int PKG_INSTALL_COMPLETE = 1;
164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 static final int SCAN_MONITOR = 1<<0;
166 static final int SCAN_NO_DEX = 1<<1;
167 static final int SCAN_FORCE_DEX = 1<<2;
168 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800169 static final int SCAN_NEW_INSTALL = 1<<4;
170 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800172 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
173 "com.android.defcontainer",
174 "com.android.defcontainer.DefaultContainerService");
175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
177 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700178 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179
Dianne Hackborn851a5412009-05-08 12:06:44 -0700180 final int mSdkVersion = Build.VERSION.SDK_INT;
181 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
182 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 final Context mContext;
185 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700186 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 final DisplayMetrics mMetrics;
188 final int mDefParseFlags;
189 final String[] mSeparateProcesses;
190
191 // This is where all application persistent data goes.
192 final File mAppDataDir;
193
Oscar Montemayora8529f62009-11-18 10:14:20 -0800194 // If Encrypted File System feature is enabled, all application persistent data
195 // should go here instead.
196 final File mSecureAppDataDir;
197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 // This is the object monitoring the framework dir.
199 final FileObserver mFrameworkInstallObserver;
200
201 // This is the object monitoring the system app dir.
202 final FileObserver mSystemInstallObserver;
203
204 // This is the object monitoring mAppInstallDir.
205 final FileObserver mAppInstallObserver;
206
207 // This is the object monitoring mDrmAppPrivateInstallDir.
208 final FileObserver mDrmAppInstallObserver;
209
210 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
211 // LOCK HELD. Can be called with mInstallLock held.
212 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 final File mFrameworkDir;
215 final File mSystemAppDir;
216 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700217 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
219 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
220 // apps.
221 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Lock for state used when installing and doing other long running
226 // operations. Methods that must be called with this lock held have
227 // the prefix "LI".
228 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 // These are the directories in the 3rd party applications installed dir
231 // that we have currently loaded packages from. Keys are the application's
232 // installed zip file (absolute codePath), and values are Package.
233 final HashMap<String, PackageParser.Package> mAppDirs =
234 new HashMap<String, PackageParser.Package>();
235
236 // Information for the parser to write more useful error messages.
237 File mScanningPath;
238 int mLastScanError;
239
240 final int[] mOutPermissions = new int[3];
241
242 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // Keys are String (package name), values are Package. This also serves
245 // as the lock for the global state. Methods that must be called with
246 // this lock held have the prefix "LP".
247 final HashMap<String, PackageParser.Package> mPackages =
248 new HashMap<String, PackageParser.Package>();
249
250 final Settings mSettings;
251 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252
253 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
254 int[] mGlobalGids;
255
256 // These are the built-in uid -> permission mappings that were read from the
257 // etc/permissions.xml file.
258 final SparseArray<HashSet<String>> mSystemPermissions =
259 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 // These are the built-in shared libraries that were read from the
262 // etc/permissions.xml file.
263 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800264
Dianne Hackborn49237342009-08-27 20:08:01 -0700265 // Temporary for building the final shared libraries for an .apk.
266 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800267
Dianne Hackborn49237342009-08-27 20:08:01 -0700268 // These are the features this devices supports that were read from the
269 // etc/permissions.xml file.
270 final HashMap<String, FeatureInfo> mAvailableFeatures =
271 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 // All available activities, for your resolving pleasure.
274 final ActivityIntentResolver mActivities =
275 new ActivityIntentResolver();
276
277 // All available receivers, for your resolving pleasure.
278 final ActivityIntentResolver mReceivers =
279 new ActivityIntentResolver();
280
281 // All available services, for your resolving pleasure.
282 final ServiceIntentResolver mServices = new ServiceIntentResolver();
283
284 // Keys are String (provider class name), values are Provider.
285 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
286 new HashMap<ComponentName, PackageParser.Provider>();
287
288 // Mapping from provider base names (first directory in content URI codePath)
289 // to the provider information.
290 final HashMap<String, PackageParser.Provider> mProviders =
291 new HashMap<String, PackageParser.Provider>();
292
293 // Mapping from instrumentation class names to info about them.
294 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
295 new HashMap<ComponentName, PackageParser.Instrumentation>();
296
297 // Mapping from permission names to info about them.
298 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
299 new HashMap<String, PackageParser.PermissionGroup>();
300
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800301 // Packages whose data we have transfered into another package, thus
302 // should no longer exist.
303 final HashSet<String> mTransferedPackages = new HashSet<String>();
304
Dianne Hackborn854060af2009-07-09 18:14:31 -0700305 // Broadcast actions that are only available to the system.
306 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 boolean mSystemReady;
309 boolean mSafeMode;
310 boolean mHasSystemUidErrors;
311
312 ApplicationInfo mAndroidApplication;
313 final ActivityInfo mResolveActivity = new ActivityInfo();
314 final ResolveInfo mResolveInfo = new ResolveInfo();
315 ComponentName mResolveComponentName;
316 PackageParser.Package mPlatformPackage;
317
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700318 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800319 final HashMap<String, ArrayList<String>> mPendingBroadcasts
320 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700321 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800322 static final int MCS_BOUND = 3;
323 static final int END_COPY = 4;
324 static final int INIT_COPY = 5;
325 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800326 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800327 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800328 static final int POST_INSTALL = 9;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700329 // Delay time in millisecs
330 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800331 private ServiceConnection mDefContainerConn = new ServiceConnection() {
332 public void onServiceConnected(ComponentName name, IBinder service) {
333 IMediaContainerService imcs =
334 IMediaContainerService.Stub.asInterface(service);
335 Message msg = mHandler.obtainMessage(MCS_BOUND, imcs);
336 mHandler.sendMessage(msg);
337 }
338
339 public void onServiceDisconnected(ComponentName name) {
340 }
341 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700342
Christopher Tate1bb69062010-02-19 17:02:12 -0800343 // Recordkeeping of restore-after-install operations that are currently in flight
344 // between the Package Manager and the Backup Manager
345 class PostInstallData {
346 public InstallArgs args;
347 public PackageInstalledInfo res;
348
349 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
350 args = _a;
351 res = _r;
352 }
353 };
354 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
355 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
356
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700357 class PackageHandler extends Handler {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800358 final ArrayList<HandlerParams> mPendingInstalls =
359 new ArrayList<HandlerParams>();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800360 // Service Connection to remote media container service to copy
361 // package uri's from external media onto secure containers
362 // or internal storage.
363 private IMediaContainerService mContainerService = null;
364
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700365 PackageHandler(Looper looper) {
366 super(looper);
367 }
368 public void handleMessage(Message msg) {
369 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800370 case INIT_COPY: {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800371 HandlerParams params = (HandlerParams) msg.obj;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800372 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800373 if (mContainerService != null) {
374 // No need to add to pending list. Use remote stub directly
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800375 params.handleStartCopy(mContainerService);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800376 } else {
377 if (mContext.bindService(service, mDefContainerConn,
378 Context.BIND_AUTO_CREATE)) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800379 mPendingInstalls.add(params);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800380 } else {
381 Log.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800382 // Indicate service bind error
383 params.handleServiceError();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800384 }
385 }
386 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800387 }
388 case MCS_BOUND: {
389 // Initialize mContainerService if needed.
390 if (msg.obj != null) {
391 mContainerService = (IMediaContainerService) msg.obj;
392 }
393 if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800394 HandlerParams params = mPendingInstalls.remove(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800395 if (params != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800396 params.handleStartCopy(mContainerService);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800397 }
398 }
399 break;
400 }
401 case MCS_UNBIND : {
402 if (mPendingInstalls.size() == 0) {
403 mContext.unbindService(mDefContainerConn);
404 mContainerService = null;
405 }
406 break;
407 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700408 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800409 String packages[];
410 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700411 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700412 int uids[];
413 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800414 if (mPendingBroadcasts == null) {
415 return;
416 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700417 size = mPendingBroadcasts.size();
418 if (size <= 0) {
419 // Nothing to be done. Just return
420 return;
421 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800422 packages = new String[size];
423 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700424 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800425 Iterator<HashMap.Entry<String, ArrayList<String>>>
426 it = mPendingBroadcasts.entrySet().iterator();
427 int i = 0;
428 while (it.hasNext() && i < size) {
429 HashMap.Entry<String, ArrayList<String>> ent = it.next();
430 packages[i] = ent.getKey();
431 components[i] = ent.getValue();
432 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700433 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800434 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700435 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800436 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700437 mPendingBroadcasts.clear();
438 }
439 // Send broadcasts
440 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800441 sendPackageChangedBroadcast(packages[i], true,
442 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700443 }
444 break;
445 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800446 case START_CLEANING_PACKAGE: {
447 String packageName = (String)msg.obj;
448 synchronized (mPackages) {
449 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
450 mSettings.mPackagesToBeCleaned.add(packageName);
451 }
452 }
453 startCleaningPackages();
454 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800455 case POST_INSTALL: {
456 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
457 PostInstallData data = mRunningInstalls.get(msg.arg1);
458 mRunningInstalls.delete(msg.arg1);
459
460 if (data != null) {
461 InstallArgs args = data.args;
462 PackageInstalledInfo res = data.res;
463
464 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
465 res.removedInfo.sendBroadcast(false, true);
466 Bundle extras = new Bundle(1);
467 extras.putInt(Intent.EXTRA_UID, res.uid);
468 final boolean update = res.removedInfo.removedPackage != null;
469 if (update) {
470 extras.putBoolean(Intent.EXTRA_REPLACING, true);
471 }
472 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
473 res.pkg.applicationInfo.packageName,
474 extras);
475 if (update) {
476 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
477 res.pkg.applicationInfo.packageName,
478 extras);
479 }
480 if (res.removedInfo.args != null) {
481 // Remove the replaced package's older resources safely now
482 synchronized (mInstallLock) {
483 res.removedInfo.args.doPostDeleteLI(true);
484 }
485 }
486 }
487 Runtime.getRuntime().gc();
488
489 if (args.observer != null) {
490 try {
491 args.observer.packageInstalled(res.name, res.returnCode);
492 } catch (RemoteException e) {
493 Log.i(TAG, "Observer no longer exists.");
494 }
495 }
496 } else {
497 Log.e(TAG, "Bogus post-install token " + msg.arg1);
498 }
499 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700500 }
501 }
502 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800503
504 static boolean installOnSd(int flags) {
505 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800506 ((flags & PackageManager.INSTALL_EXTERNAL) == 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800507 return false;
508 }
509 return true;
510 }
511
512 static boolean isFwdLocked(int flags) {
513 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
514 return true;
515 }
516 return false;
517 }
518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 public static final IPackageManager main(Context context, boolean factoryTest) {
520 PackageManagerService m = new PackageManagerService(context, factoryTest);
521 ServiceManager.addService("package", m);
522 return m;
523 }
524
525 static String[] splitString(String str, char sep) {
526 int count = 1;
527 int i = 0;
528 while ((i=str.indexOf(sep, i)) >= 0) {
529 count++;
530 i++;
531 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 String[] res = new String[count];
534 i=0;
535 count = 0;
536 int lastI=0;
537 while ((i=str.indexOf(sep, i)) >= 0) {
538 res[count] = str.substring(lastI, i);
539 count++;
540 i++;
541 lastI = i;
542 }
543 res[count] = str.substring(lastI, str.length());
544 return res;
545 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800548 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 if (mSdkVersion <= 0) {
552 Log.w(TAG, "**** ro.build.version.sdk not set!");
553 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 mContext = context;
556 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700557 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 mMetrics = new DisplayMetrics();
559 mSettings = new Settings();
560 mSettings.addSharedUserLP("android.uid.system",
561 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
562 mSettings.addSharedUserLP("android.uid.phone",
563 MULTIPLE_APPLICATION_UIDS
564 ? RADIO_UID : FIRST_APPLICATION_UID,
565 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400566 mSettings.addSharedUserLP("android.uid.log",
567 MULTIPLE_APPLICATION_UIDS
568 ? LOG_UID : FIRST_APPLICATION_UID,
569 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570
571 String separateProcesses = SystemProperties.get("debug.separate_processes");
572 if (separateProcesses != null && separateProcesses.length() > 0) {
573 if ("*".equals(separateProcesses)) {
574 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
575 mSeparateProcesses = null;
576 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
577 } else {
578 mDefParseFlags = 0;
579 mSeparateProcesses = separateProcesses.split(",");
580 Log.w(TAG, "Running with debug.separate_processes: "
581 + separateProcesses);
582 }
583 } else {
584 mDefParseFlags = 0;
585 mSeparateProcesses = null;
586 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 Installer installer = new Installer();
589 // Little hacky thing to check if installd is here, to determine
590 // whether we are running on the simulator and thus need to take
591 // care of building the /data file structure ourself.
592 // (apparently the sim now has a working installer)
593 if (installer.ping() && Process.supportsProcesses()) {
594 mInstaller = installer;
595 } else {
596 mInstaller = null;
597 }
598
599 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
600 Display d = wm.getDefaultDisplay();
601 d.getMetrics(mMetrics);
602
603 synchronized (mInstallLock) {
604 synchronized (mPackages) {
605 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700606 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 File dataDir = Environment.getDataDirectory();
609 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800610 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
612
613 if (mInstaller == null) {
614 // Make sure these dirs exist, when we are running in
615 // the simulator.
616 // Make a wide-open directory for random misc stuff.
617 File miscDir = new File(dataDir, "misc");
618 miscDir.mkdirs();
619 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800620 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 mDrmAppPrivateInstallDir.mkdirs();
622 }
623
624 readPermissions();
625
626 mRestoredSettings = mSettings.readLP();
627 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800628
629 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800631
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800632 // Set flag to monitor and not change apk file paths when
633 // scanning install directories.
634 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700635 if (mNoDexOpt) {
636 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800637 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700638 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700643 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700646 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 /**
649 * Out of paranoia, ensure that everything in the boot class
650 * path has been dexed.
651 */
652 String bootClassPath = System.getProperty("java.boot.class.path");
653 if (bootClassPath != null) {
654 String[] paths = splitString(bootClassPath, ':');
655 for (int i=0; i<paths.length; i++) {
656 try {
657 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
658 libFiles.add(paths[i]);
659 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700660 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 }
662 } catch (FileNotFoundException e) {
663 Log.w(TAG, "Boot class path not found: " + paths[i]);
664 } catch (IOException e) {
665 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
666 }
667 }
668 } else {
669 Log.w(TAG, "No BOOTCLASSPATH found!");
670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 /**
673 * Also ensure all external libraries have had dexopt run on them.
674 */
675 if (mSharedLibraries.size() > 0) {
676 Iterator<String> libs = mSharedLibraries.values().iterator();
677 while (libs.hasNext()) {
678 String lib = libs.next();
679 try {
680 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
681 libFiles.add(lib);
682 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700683 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 }
685 } catch (FileNotFoundException e) {
686 Log.w(TAG, "Library not found: " + lib);
687 } catch (IOException e) {
688 Log.w(TAG, "Exception reading library: " + lib, e);
689 }
690 }
691 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 // Gross hack for now: we know this file doesn't contain any
694 // code, so don't dexopt it to avoid the resulting log spew.
695 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 /**
698 * And there are a number of commands implemented in Java, which
699 * we currently need to do the dexopt on so that they can be
700 * run from a non-root shell.
701 */
702 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700703 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 for (int i=0; i<frameworkFiles.length; i++) {
705 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
706 String path = libPath.getPath();
707 // Skip the file if we alrady did it.
708 if (libFiles.contains(path)) {
709 continue;
710 }
711 // Skip the file if it is not a type we want to dexopt.
712 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
713 continue;
714 }
715 try {
716 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
717 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700718 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
720 } catch (FileNotFoundException e) {
721 Log.w(TAG, "Jar not found: " + path);
722 } catch (IOException e) {
723 Log.w(TAG, "Exception reading jar: " + path, e);
724 }
725 }
726 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800727
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700728 if (didDexOpt) {
729 // If we had to do a dexopt of one of the previous
730 // things, then something on the system has changed.
731 // Consider this significant, and wipe away all other
732 // existing dexopt files to ensure we don't leave any
733 // dangling around.
734 String[] files = mDalvikCacheDir.list();
735 if (files != null) {
736 for (int i=0; i<files.length; i++) {
737 String fn = files[i];
738 if (fn.startsWith("data@app@")
739 || fn.startsWith("data@app-private@")) {
740 Log.i(TAG, "Pruning dalvik file: " + fn);
741 (new File(mDalvikCacheDir, fn)).delete();
742 }
743 }
744 }
745 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800747
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800748 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 mFrameworkInstallObserver = new AppDirObserver(
750 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
751 mFrameworkInstallObserver.startWatching();
752 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800753 scanMode | SCAN_NO_DEX);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800754
755 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
757 mSystemInstallObserver = new AppDirObserver(
758 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
759 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800760 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800761
762 if (mInstaller != null) {
763 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
764 mInstaller.moveFiles();
765 }
766
767 // Prune any system packages that no longer exist.
768 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
769 while (psit.hasNext()) {
770 PackageSetting ps = psit.next();
771 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800772 && !mPackages.containsKey(ps.name)
773 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800774 psit.remove();
775 String msg = "System package " + ps.name
776 + " no longer exists; wiping its data";
777 reportSettingsProblem(Log.WARN, msg);
778 if (mInstaller != null) {
779 // XXX how to set useEncryptedFSDir for packages that
780 // are not encrypted?
781 mInstaller.remove(ps.name, true);
782 }
783 }
784 }
785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 mAppInstallDir = new File(dataDir, "app");
787 if (mInstaller == null) {
788 // Make sure these dirs exist, when we are running in
789 // the simulator.
790 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
791 }
792 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800793 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 //clean up list
795 for(int i = 0; i < deletePkgsList.size(); i++) {
796 //clean up here
797 cleanupInstallFailedPackage(deletePkgsList.get(i));
798 }
799 //delete tmp files
800 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800801
802 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 SystemClock.uptimeMillis());
804 mAppInstallObserver = new AppDirObserver(
805 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
806 mAppInstallObserver.startWatching();
807 scanDirLI(mAppInstallDir, 0, scanMode);
808
809 mDrmAppInstallObserver = new AppDirObserver(
810 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
811 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800812 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800814 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 SystemClock.uptimeMillis());
816 Log.i(TAG, "Time to scan packages: "
817 + ((SystemClock.uptimeMillis()-startTime)/1000f)
818 + " seconds");
819
820 updatePermissionsLP();
821
822 mSettings.writeLP();
823
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800824 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 // Now after opening every single application zip, make sure they
828 // are all flushed. Not really needed, but keeps things nice and
829 // tidy.
830 Runtime.getRuntime().gc();
831 } // synchronized (mPackages)
832 } // synchronized (mInstallLock)
833 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 @Override
836 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
837 throws RemoteException {
838 try {
839 return super.onTransact(code, data, reply, flags);
840 } catch (RuntimeException e) {
841 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
842 Log.e(TAG, "Package Manager Crash", e);
843 }
844 throw e;
845 }
846 }
847
Dianne Hackborne6620b22010-01-22 14:46:21 -0800848 void cleanupInstallFailedPackage(PackageSetting ps) {
849 Log.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 if (mInstaller != null) {
Kenny Rootbdbc9252010-01-28 12:03:49 -0800851 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
852 int retCode = mInstaller.remove(ps.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 if (retCode < 0) {
854 Log.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800855 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 }
857 } else {
858 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800859 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 File dataDir = new File(pkg.applicationInfo.dataDir);
861 dataDir.delete();
862 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800863 if (ps.codePath != null) {
864 if (!ps.codePath.delete()) {
865 Log.w(TAG, "Unable to remove old code file: " + ps.codePath);
866 }
867 }
868 if (ps.resourcePath != null) {
869 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
870 Log.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
871 }
872 }
873 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 }
875
876 void readPermissions() {
877 // Read permissions from .../etc/permission directory.
878 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
879 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
880 Log.w(TAG, "No directory " + libraryDir + ", skipping");
881 return;
882 }
883 if (!libraryDir.canRead()) {
884 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
885 return;
886 }
887
888 // Iterate over the files in the directory and scan .xml files
889 for (File f : libraryDir.listFiles()) {
890 // We'll read platform.xml last
891 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
892 continue;
893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 if (!f.getPath().endsWith(".xml")) {
896 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
897 continue;
898 }
899 if (!f.canRead()) {
900 Log.w(TAG, "Permissions library file " + f + " cannot be read");
901 continue;
902 }
903
904 readPermissionsFromXml(f);
905 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
908 final File permFile = new File(Environment.getRootDirectory(),
909 "etc/permissions/platform.xml");
910 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800911
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700912 StringBuilder sb = new StringBuilder(128);
913 sb.append("Libs:");
914 Iterator<String> it = mSharedLibraries.keySet().iterator();
915 while (it.hasNext()) {
916 sb.append(' ');
917 String name = it.next();
918 sb.append(name);
919 sb.append(':');
920 sb.append(mSharedLibraries.get(name));
921 }
922 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800923
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700924 sb.setLength(0);
925 sb.append("Features:");
926 it = mAvailableFeatures.keySet().iterator();
927 while (it.hasNext()) {
928 sb.append(' ');
929 sb.append(it.next());
930 }
931 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800933
934 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935 FileReader permReader = null;
936 try {
937 permReader = new FileReader(permFile);
938 } catch (FileNotFoundException e) {
939 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
940 return;
941 }
942
943 try {
944 XmlPullParser parser = Xml.newPullParser();
945 parser.setInput(permReader);
946
947 XmlUtils.beginDocument(parser, "permissions");
948
949 while (true) {
950 XmlUtils.nextElement(parser);
951 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
952 break;
953 }
954
955 String name = parser.getName();
956 if ("group".equals(name)) {
957 String gidStr = parser.getAttributeValue(null, "gid");
958 if (gidStr != null) {
959 int gid = Integer.parseInt(gidStr);
960 mGlobalGids = appendInt(mGlobalGids, gid);
961 } else {
962 Log.w(TAG, "<group> without gid at "
963 + parser.getPositionDescription());
964 }
965
966 XmlUtils.skipCurrentTag(parser);
967 continue;
968 } else if ("permission".equals(name)) {
969 String perm = parser.getAttributeValue(null, "name");
970 if (perm == null) {
971 Log.w(TAG, "<permission> without name at "
972 + parser.getPositionDescription());
973 XmlUtils.skipCurrentTag(parser);
974 continue;
975 }
976 perm = perm.intern();
977 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 } else if ("assign-permission".equals(name)) {
980 String perm = parser.getAttributeValue(null, "name");
981 if (perm == null) {
982 Log.w(TAG, "<assign-permission> without name at "
983 + parser.getPositionDescription());
984 XmlUtils.skipCurrentTag(parser);
985 continue;
986 }
987 String uidStr = parser.getAttributeValue(null, "uid");
988 if (uidStr == null) {
989 Log.w(TAG, "<assign-permission> without uid at "
990 + parser.getPositionDescription());
991 XmlUtils.skipCurrentTag(parser);
992 continue;
993 }
994 int uid = Process.getUidForName(uidStr);
995 if (uid < 0) {
996 Log.w(TAG, "<assign-permission> with unknown uid \""
997 + uidStr + "\" at "
998 + parser.getPositionDescription());
999 XmlUtils.skipCurrentTag(parser);
1000 continue;
1001 }
1002 perm = perm.intern();
1003 HashSet<String> perms = mSystemPermissions.get(uid);
1004 if (perms == null) {
1005 perms = new HashSet<String>();
1006 mSystemPermissions.put(uid, perms);
1007 }
1008 perms.add(perm);
1009 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } else if ("library".equals(name)) {
1012 String lname = parser.getAttributeValue(null, "name");
1013 String lfile = parser.getAttributeValue(null, "file");
1014 if (lname == null) {
1015 Log.w(TAG, "<library> without name at "
1016 + parser.getPositionDescription());
1017 } else if (lfile == null) {
1018 Log.w(TAG, "<library> without file at "
1019 + parser.getPositionDescription());
1020 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001021 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001022 mSharedLibraries.put(lname, lfile);
1023 }
1024 XmlUtils.skipCurrentTag(parser);
1025 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001026
Dianne Hackborn49237342009-08-27 20:08:01 -07001027 } else if ("feature".equals(name)) {
1028 String fname = parser.getAttributeValue(null, "name");
1029 if (fname == null) {
1030 Log.w(TAG, "<feature> without name at "
1031 + parser.getPositionDescription());
1032 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001033 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001034 FeatureInfo fi = new FeatureInfo();
1035 fi.name = fname;
1036 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 }
1038 XmlUtils.skipCurrentTag(parser);
1039 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 } else {
1042 XmlUtils.skipCurrentTag(parser);
1043 continue;
1044 }
1045
1046 }
1047 } catch (XmlPullParserException e) {
1048 Log.w(TAG, "Got execption parsing permissions.", e);
1049 } catch (IOException e) {
1050 Log.w(TAG, "Got execption parsing permissions.", e);
1051 }
1052 }
1053
1054 void readPermission(XmlPullParser parser, String name)
1055 throws IOException, XmlPullParserException {
1056
1057 name = name.intern();
1058
1059 BasePermission bp = mSettings.mPermissions.get(name);
1060 if (bp == null) {
1061 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1062 mSettings.mPermissions.put(name, bp);
1063 }
1064 int outerDepth = parser.getDepth();
1065 int type;
1066 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1067 && (type != XmlPullParser.END_TAG
1068 || parser.getDepth() > outerDepth)) {
1069 if (type == XmlPullParser.END_TAG
1070 || type == XmlPullParser.TEXT) {
1071 continue;
1072 }
1073
1074 String tagName = parser.getName();
1075 if ("group".equals(tagName)) {
1076 String gidStr = parser.getAttributeValue(null, "gid");
1077 if (gidStr != null) {
1078 int gid = Process.getGidForName(gidStr);
1079 bp.gids = appendInt(bp.gids, gid);
1080 } else {
1081 Log.w(TAG, "<group> without gid at "
1082 + parser.getPositionDescription());
1083 }
1084 }
1085 XmlUtils.skipCurrentTag(parser);
1086 }
1087 }
1088
1089 static int[] appendInt(int[] cur, int val) {
1090 if (cur == null) {
1091 return new int[] { val };
1092 }
1093 final int N = cur.length;
1094 for (int i=0; i<N; i++) {
1095 if (cur[i] == val) {
1096 return cur;
1097 }
1098 }
1099 int[] ret = new int[N+1];
1100 System.arraycopy(cur, 0, ret, 0, N);
1101 ret[N] = val;
1102 return ret;
1103 }
1104
1105 static int[] appendInts(int[] cur, int[] add) {
1106 if (add == null) return cur;
1107 if (cur == null) return add;
1108 final int N = add.length;
1109 for (int i=0; i<N; i++) {
1110 cur = appendInt(cur, add[i]);
1111 }
1112 return cur;
1113 }
1114
1115 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001116 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1117 // The package has been uninstalled but has retained data and resources.
1118 return PackageParser.generatePackageInfo(p, null, flags);
1119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 final PackageSetting ps = (PackageSetting)p.mExtras;
1121 if (ps == null) {
1122 return null;
1123 }
1124 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1125 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1126 }
1127
1128 public PackageInfo getPackageInfo(String packageName, int flags) {
1129 synchronized (mPackages) {
1130 PackageParser.Package p = mPackages.get(packageName);
1131 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001132 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 + ": " + p);
1134 if (p != null) {
1135 return generatePackageInfo(p, flags);
1136 }
1137 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1138 return generatePackageInfoFromSettingsLP(packageName, flags);
1139 }
1140 }
1141 return null;
1142 }
1143
Dianne Hackborn47096932010-02-11 15:57:09 -08001144 public String[] currentToCanonicalPackageNames(String[] names) {
1145 String[] out = new String[names.length];
1146 synchronized (mPackages) {
1147 for (int i=names.length-1; i>=0; i--) {
1148 PackageSetting ps = mSettings.mPackages.get(names[i]);
1149 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1150 }
1151 }
1152 return out;
1153 }
1154
1155 public String[] canonicalToCurrentPackageNames(String[] names) {
1156 String[] out = new String[names.length];
1157 synchronized (mPackages) {
1158 for (int i=names.length-1; i>=0; i--) {
1159 String cur = mSettings.mRenamedPackages.get(names[i]);
1160 out[i] = cur != null ? cur : names[i];
1161 }
1162 }
1163 return out;
1164 }
1165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 public int getPackageUid(String packageName) {
1167 synchronized (mPackages) {
1168 PackageParser.Package p = mPackages.get(packageName);
1169 if(p != null) {
1170 return p.applicationInfo.uid;
1171 }
1172 PackageSetting ps = mSettings.mPackages.get(packageName);
1173 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1174 return -1;
1175 }
1176 p = ps.pkg;
1177 return p != null ? p.applicationInfo.uid : -1;
1178 }
1179 }
1180
1181 public int[] getPackageGids(String packageName) {
1182 synchronized (mPackages) {
1183 PackageParser.Package p = mPackages.get(packageName);
1184 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001185 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 + ": " + p);
1187 if (p != null) {
1188 final PackageSetting ps = (PackageSetting)p.mExtras;
1189 final SharedUserSetting suid = ps.sharedUser;
1190 return suid != null ? suid.gids : ps.gids;
1191 }
1192 }
1193 // stupid thing to indicate an error.
1194 return new int[0];
1195 }
1196
1197 public PermissionInfo getPermissionInfo(String name, int flags) {
1198 synchronized (mPackages) {
1199 final BasePermission p = mSettings.mPermissions.get(name);
1200 if (p != null && p.perm != null) {
1201 return PackageParser.generatePermissionInfo(p.perm, flags);
1202 }
1203 return null;
1204 }
1205 }
1206
1207 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1208 synchronized (mPackages) {
1209 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1210 for (BasePermission p : mSettings.mPermissions.values()) {
1211 if (group == null) {
1212 if (p.perm.info.group == null) {
1213 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1214 }
1215 } else {
1216 if (group.equals(p.perm.info.group)) {
1217 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1218 }
1219 }
1220 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 if (out.size() > 0) {
1223 return out;
1224 }
1225 return mPermissionGroups.containsKey(group) ? out : null;
1226 }
1227 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1230 synchronized (mPackages) {
1231 return PackageParser.generatePermissionGroupInfo(
1232 mPermissionGroups.get(name), flags);
1233 }
1234 }
1235
1236 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1237 synchronized (mPackages) {
1238 final int N = mPermissionGroups.size();
1239 ArrayList<PermissionGroupInfo> out
1240 = new ArrayList<PermissionGroupInfo>(N);
1241 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1242 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1243 }
1244 return out;
1245 }
1246 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1249 PackageSetting ps = mSettings.mPackages.get(packageName);
1250 if(ps != null) {
1251 if(ps.pkg == null) {
1252 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1253 if(pInfo != null) {
1254 return pInfo.applicationInfo;
1255 }
1256 return null;
1257 }
1258 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1259 }
1260 return null;
1261 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1264 PackageSetting ps = mSettings.mPackages.get(packageName);
1265 if(ps != null) {
1266 if(ps.pkg == null) {
1267 ps.pkg = new PackageParser.Package(packageName);
1268 ps.pkg.applicationInfo.packageName = packageName;
1269 }
1270 return generatePackageInfo(ps.pkg, flags);
1271 }
1272 return null;
1273 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1276 synchronized (mPackages) {
1277 PackageParser.Package p = mPackages.get(packageName);
1278 if (Config.LOGV) Log.v(
1279 TAG, "getApplicationInfo " + packageName
1280 + ": " + p);
1281 if (p != null) {
1282 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001283 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 }
1285 if ("android".equals(packageName)||"system".equals(packageName)) {
1286 return mAndroidApplication;
1287 }
1288 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1289 return generateApplicationInfoFromSettingsLP(packageName, flags);
1290 }
1291 }
1292 return null;
1293 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001294
1295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1297 mContext.enforceCallingOrSelfPermission(
1298 android.Manifest.permission.CLEAR_APP_CACHE, null);
1299 // Queue up an async operation since clearing cache may take a little while.
1300 mHandler.post(new Runnable() {
1301 public void run() {
1302 mHandler.removeCallbacks(this);
1303 int retCode = -1;
1304 if (mInstaller != null) {
1305 retCode = mInstaller.freeCache(freeStorageSize);
1306 if (retCode < 0) {
1307 Log.w(TAG, "Couldn't clear application caches");
1308 }
1309 } //end if mInstaller
1310 if (observer != null) {
1311 try {
1312 observer.onRemoveCompleted(null, (retCode >= 0));
1313 } catch (RemoteException e) {
1314 Log.w(TAG, "RemoveException when invoking call back");
1315 }
1316 }
1317 }
1318 });
1319 }
1320
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001321 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001322 mContext.enforceCallingOrSelfPermission(
1323 android.Manifest.permission.CLEAR_APP_CACHE, null);
1324 // Queue up an async operation since clearing cache may take a little while.
1325 mHandler.post(new Runnable() {
1326 public void run() {
1327 mHandler.removeCallbacks(this);
1328 int retCode = -1;
1329 if (mInstaller != null) {
1330 retCode = mInstaller.freeCache(freeStorageSize);
1331 if (retCode < 0) {
1332 Log.w(TAG, "Couldn't clear application caches");
1333 }
1334 }
1335 if(pi != null) {
1336 try {
1337 // Callback via pending intent
1338 int code = (retCode >= 0) ? 1 : 0;
1339 pi.sendIntent(null, code, null,
1340 null, null);
1341 } catch (SendIntentException e1) {
1342 Log.i(TAG, "Failed to send pending intent");
1343 }
1344 }
1345 }
1346 });
1347 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1350 synchronized (mPackages) {
1351 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001352
1353 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001355 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 }
1357 if (mResolveComponentName.equals(component)) {
1358 return mResolveActivity;
1359 }
1360 }
1361 return null;
1362 }
1363
1364 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1365 synchronized (mPackages) {
1366 PackageParser.Activity a = mReceivers.mActivities.get(component);
1367 if (Config.LOGV) Log.v(
1368 TAG, "getReceiverInfo " + component + ": " + a);
1369 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1370 return PackageParser.generateActivityInfo(a, flags);
1371 }
1372 }
1373 return null;
1374 }
1375
1376 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1377 synchronized (mPackages) {
1378 PackageParser.Service s = mServices.mServices.get(component);
1379 if (Config.LOGV) Log.v(
1380 TAG, "getServiceInfo " + component + ": " + s);
1381 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1382 return PackageParser.generateServiceInfo(s, flags);
1383 }
1384 }
1385 return null;
1386 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 public String[] getSystemSharedLibraryNames() {
1389 Set<String> libSet;
1390 synchronized (mPackages) {
1391 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001392 int size = libSet.size();
1393 if (size > 0) {
1394 String[] libs = new String[size];
1395 libSet.toArray(libs);
1396 return libs;
1397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001399 return null;
1400 }
1401
1402 public FeatureInfo[] getSystemAvailableFeatures() {
1403 Collection<FeatureInfo> featSet;
1404 synchronized (mPackages) {
1405 featSet = mAvailableFeatures.values();
1406 int size = featSet.size();
1407 if (size > 0) {
1408 FeatureInfo[] features = new FeatureInfo[size+1];
1409 featSet.toArray(features);
1410 FeatureInfo fi = new FeatureInfo();
1411 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1412 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1413 features[size] = fi;
1414 return features;
1415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 }
1417 return null;
1418 }
1419
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001420 public boolean hasSystemFeature(String name) {
1421 synchronized (mPackages) {
1422 return mAvailableFeatures.containsKey(name);
1423 }
1424 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 public int checkPermission(String permName, String pkgName) {
1427 synchronized (mPackages) {
1428 PackageParser.Package p = mPackages.get(pkgName);
1429 if (p != null && p.mExtras != null) {
1430 PackageSetting ps = (PackageSetting)p.mExtras;
1431 if (ps.sharedUser != null) {
1432 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1433 return PackageManager.PERMISSION_GRANTED;
1434 }
1435 } else if (ps.grantedPermissions.contains(permName)) {
1436 return PackageManager.PERMISSION_GRANTED;
1437 }
1438 }
1439 }
1440 return PackageManager.PERMISSION_DENIED;
1441 }
1442
1443 public int checkUidPermission(String permName, int uid) {
1444 synchronized (mPackages) {
1445 Object obj = mSettings.getUserIdLP(uid);
1446 if (obj != null) {
1447 if (obj instanceof SharedUserSetting) {
1448 SharedUserSetting sus = (SharedUserSetting)obj;
1449 if (sus.grantedPermissions.contains(permName)) {
1450 return PackageManager.PERMISSION_GRANTED;
1451 }
1452 } else if (obj instanceof PackageSetting) {
1453 PackageSetting ps = (PackageSetting)obj;
1454 if (ps.grantedPermissions.contains(permName)) {
1455 return PackageManager.PERMISSION_GRANTED;
1456 }
1457 }
1458 } else {
1459 HashSet<String> perms = mSystemPermissions.get(uid);
1460 if (perms != null && perms.contains(permName)) {
1461 return PackageManager.PERMISSION_GRANTED;
1462 }
1463 }
1464 }
1465 return PackageManager.PERMISSION_DENIED;
1466 }
1467
1468 private BasePermission findPermissionTreeLP(String permName) {
1469 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1470 if (permName.startsWith(bp.name) &&
1471 permName.length() > bp.name.length() &&
1472 permName.charAt(bp.name.length()) == '.') {
1473 return bp;
1474 }
1475 }
1476 return null;
1477 }
1478
1479 private BasePermission checkPermissionTreeLP(String permName) {
1480 if (permName != null) {
1481 BasePermission bp = findPermissionTreeLP(permName);
1482 if (bp != null) {
1483 if (bp.uid == Binder.getCallingUid()) {
1484 return bp;
1485 }
1486 throw new SecurityException("Calling uid "
1487 + Binder.getCallingUid()
1488 + " is not allowed to add to permission tree "
1489 + bp.name + " owned by uid " + bp.uid);
1490 }
1491 }
1492 throw new SecurityException("No permission tree found for " + permName);
1493 }
1494
1495 public boolean addPermission(PermissionInfo info) {
1496 synchronized (mPackages) {
1497 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1498 throw new SecurityException("Label must be specified in permission");
1499 }
1500 BasePermission tree = checkPermissionTreeLP(info.name);
1501 BasePermission bp = mSettings.mPermissions.get(info.name);
1502 boolean added = bp == null;
1503 if (added) {
1504 bp = new BasePermission(info.name, tree.sourcePackage,
1505 BasePermission.TYPE_DYNAMIC);
1506 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1507 throw new SecurityException(
1508 "Not allowed to modify non-dynamic permission "
1509 + info.name);
1510 }
1511 bp.perm = new PackageParser.Permission(tree.perm.owner,
1512 new PermissionInfo(info));
1513 bp.perm.info.packageName = tree.perm.info.packageName;
1514 bp.uid = tree.uid;
1515 if (added) {
1516 mSettings.mPermissions.put(info.name, bp);
1517 }
1518 mSettings.writeLP();
1519 return added;
1520 }
1521 }
1522
1523 public void removePermission(String name) {
1524 synchronized (mPackages) {
1525 checkPermissionTreeLP(name);
1526 BasePermission bp = mSettings.mPermissions.get(name);
1527 if (bp != null) {
1528 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1529 throw new SecurityException(
1530 "Not allowed to modify non-dynamic permission "
1531 + name);
1532 }
1533 mSettings.mPermissions.remove(name);
1534 mSettings.writeLP();
1535 }
1536 }
1537 }
1538
Dianne Hackborn854060af2009-07-09 18:14:31 -07001539 public boolean isProtectedBroadcast(String actionName) {
1540 synchronized (mPackages) {
1541 return mProtectedBroadcasts.contains(actionName);
1542 }
1543 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 public int checkSignatures(String pkg1, String pkg2) {
1546 synchronized (mPackages) {
1547 PackageParser.Package p1 = mPackages.get(pkg1);
1548 PackageParser.Package p2 = mPackages.get(pkg2);
1549 if (p1 == null || p1.mExtras == null
1550 || p2 == null || p2.mExtras == null) {
1551 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1552 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001553 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555 }
1556
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001557 public int checkUidSignatures(int uid1, int uid2) {
1558 synchronized (mPackages) {
1559 Signature[] s1;
1560 Signature[] s2;
1561 Object obj = mSettings.getUserIdLP(uid1);
1562 if (obj != null) {
1563 if (obj instanceof SharedUserSetting) {
1564 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1565 } else if (obj instanceof PackageSetting) {
1566 s1 = ((PackageSetting)obj).signatures.mSignatures;
1567 } else {
1568 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1569 }
1570 } else {
1571 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1572 }
1573 obj = mSettings.getUserIdLP(uid2);
1574 if (obj != null) {
1575 if (obj instanceof SharedUserSetting) {
1576 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1577 } else if (obj instanceof PackageSetting) {
1578 s2 = ((PackageSetting)obj).signatures.mSignatures;
1579 } else {
1580 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1581 }
1582 } else {
1583 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1584 }
1585 return checkSignaturesLP(s1, s2);
1586 }
1587 }
1588
1589 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1590 if (s1 == null) {
1591 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1593 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1594 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001595 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1597 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001598 final int N1 = s1.length;
1599 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 for (int i=0; i<N1; i++) {
1601 boolean match = false;
1602 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001603 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 match = true;
1605 break;
1606 }
1607 }
1608 if (!match) {
1609 return PackageManager.SIGNATURE_NO_MATCH;
1610 }
1611 }
1612 return PackageManager.SIGNATURE_MATCH;
1613 }
1614
1615 public String[] getPackagesForUid(int uid) {
1616 synchronized (mPackages) {
1617 Object obj = mSettings.getUserIdLP(uid);
1618 if (obj instanceof SharedUserSetting) {
1619 SharedUserSetting sus = (SharedUserSetting)obj;
1620 final int N = sus.packages.size();
1621 String[] res = new String[N];
1622 Iterator<PackageSetting> it = sus.packages.iterator();
1623 int i=0;
1624 while (it.hasNext()) {
1625 res[i++] = it.next().name;
1626 }
1627 return res;
1628 } else if (obj instanceof PackageSetting) {
1629 PackageSetting ps = (PackageSetting)obj;
1630 return new String[] { ps.name };
1631 }
1632 }
1633 return null;
1634 }
1635
1636 public String getNameForUid(int uid) {
1637 synchronized (mPackages) {
1638 Object obj = mSettings.getUserIdLP(uid);
1639 if (obj instanceof SharedUserSetting) {
1640 SharedUserSetting sus = (SharedUserSetting)obj;
1641 return sus.name + ":" + sus.userId;
1642 } else if (obj instanceof PackageSetting) {
1643 PackageSetting ps = (PackageSetting)obj;
1644 return ps.name;
1645 }
1646 }
1647 return null;
1648 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 public int getUidForSharedUser(String sharedUserName) {
1651 if(sharedUserName == null) {
1652 return -1;
1653 }
1654 synchronized (mPackages) {
1655 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1656 if(suid == null) {
1657 return -1;
1658 }
1659 return suid.userId;
1660 }
1661 }
1662
1663 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1664 int flags) {
1665 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001666 return chooseBestActivity(intent, resolvedType, flags, query);
1667 }
1668
Mihai Predaeae850c2009-05-13 10:13:48 +02001669 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1670 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 if (query != null) {
1672 final int N = query.size();
1673 if (N == 1) {
1674 return query.get(0);
1675 } else if (N > 1) {
1676 // If there is more than one activity with the same priority,
1677 // then let the user decide between them.
1678 ResolveInfo r0 = query.get(0);
1679 ResolveInfo r1 = query.get(1);
1680 if (false) {
1681 System.out.println(r0.activityInfo.name +
1682 "=" + r0.priority + " vs " +
1683 r1.activityInfo.name +
1684 "=" + r1.priority);
1685 }
1686 // If the first activity has a higher priority, or a different
1687 // default, then it is always desireable to pick it.
1688 if (r0.priority != r1.priority
1689 || r0.preferredOrder != r1.preferredOrder
1690 || r0.isDefault != r1.isDefault) {
1691 return query.get(0);
1692 }
1693 // If we have saved a preference for a preferred activity for
1694 // this Intent, use that.
1695 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1696 flags, query, r0.priority);
1697 if (ri != null) {
1698 return ri;
1699 }
1700 return mResolveInfo;
1701 }
1702 }
1703 return null;
1704 }
1705
1706 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1707 int flags, List<ResolveInfo> query, int priority) {
1708 synchronized (mPackages) {
1709 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1710 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001711 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1713 if (prefs != null && prefs.size() > 0) {
1714 // First figure out how good the original match set is.
1715 // We will only allow preferred activities that came
1716 // from the same match quality.
1717 int match = 0;
1718 final int N = query.size();
1719 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1720 for (int j=0; j<N; j++) {
1721 ResolveInfo ri = query.get(j);
1722 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1723 + ": 0x" + Integer.toHexString(match));
1724 if (ri.match > match) match = ri.match;
1725 }
1726 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1727 + Integer.toHexString(match));
1728 match &= IntentFilter.MATCH_CATEGORY_MASK;
1729 final int M = prefs.size();
1730 for (int i=0; i<M; i++) {
1731 PreferredActivity pa = prefs.get(i);
1732 if (pa.mMatch != match) {
1733 continue;
1734 }
1735 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1736 if (DEBUG_PREFERRED) {
1737 Log.v(TAG, "Got preferred activity:");
1738 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1739 }
1740 if (ai != null) {
1741 for (int j=0; j<N; j++) {
1742 ResolveInfo ri = query.get(j);
1743 if (!ri.activityInfo.applicationInfo.packageName
1744 .equals(ai.applicationInfo.packageName)) {
1745 continue;
1746 }
1747 if (!ri.activityInfo.name.equals(ai.name)) {
1748 continue;
1749 }
1750
1751 // Okay we found a previously set preferred app.
1752 // If the result set is different from when this
1753 // was created, we need to clear it and re-ask the
1754 // user their preference.
1755 if (!pa.sameSet(query, priority)) {
1756 Log.i(TAG, "Result set changed, dropping preferred activity for "
1757 + intent + " type " + resolvedType);
1758 mSettings.mPreferredActivities.removeFilter(pa);
1759 return null;
1760 }
1761
1762 // Yay!
1763 return ri;
1764 }
1765 }
1766 }
1767 }
1768 }
1769 return null;
1770 }
1771
1772 public List<ResolveInfo> queryIntentActivities(Intent intent,
1773 String resolvedType, int flags) {
1774 ComponentName comp = intent.getComponent();
1775 if (comp != null) {
1776 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1777 ActivityInfo ai = getActivityInfo(comp, flags);
1778 if (ai != null) {
1779 ResolveInfo ri = new ResolveInfo();
1780 ri.activityInfo = ai;
1781 list.add(ri);
1782 }
1783 return list;
1784 }
1785
1786 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001787 String pkgName = intent.getPackage();
1788 if (pkgName == null) {
1789 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1790 resolvedType, flags);
1791 }
1792 PackageParser.Package pkg = mPackages.get(pkgName);
1793 if (pkg != null) {
1794 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1795 resolvedType, flags, pkg.activities);
1796 }
1797 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 }
1799 }
1800
1801 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1802 Intent[] specifics, String[] specificTypes, Intent intent,
1803 String resolvedType, int flags) {
1804 final String resultsAction = intent.getAction();
1805
1806 List<ResolveInfo> results = queryIntentActivities(
1807 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1808 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1809
1810 int specificsPos = 0;
1811 int N;
1812
1813 // todo: note that the algorithm used here is O(N^2). This
1814 // isn't a problem in our current environment, but if we start running
1815 // into situations where we have more than 5 or 10 matches then this
1816 // should probably be changed to something smarter...
1817
1818 // First we go through and resolve each of the specific items
1819 // that were supplied, taking care of removing any corresponding
1820 // duplicate items in the generic resolve list.
1821 if (specifics != null) {
1822 for (int i=0; i<specifics.length; i++) {
1823 final Intent sintent = specifics[i];
1824 if (sintent == null) {
1825 continue;
1826 }
1827
1828 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1829 String action = sintent.getAction();
1830 if (resultsAction != null && resultsAction.equals(action)) {
1831 // If this action was explicitly requested, then don't
1832 // remove things that have it.
1833 action = null;
1834 }
1835 ComponentName comp = sintent.getComponent();
1836 ResolveInfo ri = null;
1837 ActivityInfo ai = null;
1838 if (comp == null) {
1839 ri = resolveIntent(
1840 sintent,
1841 specificTypes != null ? specificTypes[i] : null,
1842 flags);
1843 if (ri == null) {
1844 continue;
1845 }
1846 if (ri == mResolveInfo) {
1847 // ACK! Must do something better with this.
1848 }
1849 ai = ri.activityInfo;
1850 comp = new ComponentName(ai.applicationInfo.packageName,
1851 ai.name);
1852 } else {
1853 ai = getActivityInfo(comp, flags);
1854 if (ai == null) {
1855 continue;
1856 }
1857 }
1858
1859 // Look for any generic query activities that are duplicates
1860 // of this specific one, and remove them from the results.
1861 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1862 N = results.size();
1863 int j;
1864 for (j=specificsPos; j<N; j++) {
1865 ResolveInfo sri = results.get(j);
1866 if ((sri.activityInfo.name.equals(comp.getClassName())
1867 && sri.activityInfo.applicationInfo.packageName.equals(
1868 comp.getPackageName()))
1869 || (action != null && sri.filter.matchAction(action))) {
1870 results.remove(j);
1871 if (Config.LOGV) Log.v(
1872 TAG, "Removing duplicate item from " + j
1873 + " due to specific " + specificsPos);
1874 if (ri == null) {
1875 ri = sri;
1876 }
1877 j--;
1878 N--;
1879 }
1880 }
1881
1882 // Add this specific item to its proper place.
1883 if (ri == null) {
1884 ri = new ResolveInfo();
1885 ri.activityInfo = ai;
1886 }
1887 results.add(specificsPos, ri);
1888 ri.specificIndex = i;
1889 specificsPos++;
1890 }
1891 }
1892
1893 // Now we go through the remaining generic results and remove any
1894 // duplicate actions that are found here.
1895 N = results.size();
1896 for (int i=specificsPos; i<N-1; i++) {
1897 final ResolveInfo rii = results.get(i);
1898 if (rii.filter == null) {
1899 continue;
1900 }
1901
1902 // Iterate over all of the actions of this result's intent
1903 // filter... typically this should be just one.
1904 final Iterator<String> it = rii.filter.actionsIterator();
1905 if (it == null) {
1906 continue;
1907 }
1908 while (it.hasNext()) {
1909 final String action = it.next();
1910 if (resultsAction != null && resultsAction.equals(action)) {
1911 // If this action was explicitly requested, then don't
1912 // remove things that have it.
1913 continue;
1914 }
1915 for (int j=i+1; j<N; j++) {
1916 final ResolveInfo rij = results.get(j);
1917 if (rij.filter != null && rij.filter.hasAction(action)) {
1918 results.remove(j);
1919 if (Config.LOGV) Log.v(
1920 TAG, "Removing duplicate item from " + j
1921 + " due to action " + action + " at " + i);
1922 j--;
1923 N--;
1924 }
1925 }
1926 }
1927
1928 // If the caller didn't request filter information, drop it now
1929 // so we don't have to marshall/unmarshall it.
1930 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1931 rii.filter = null;
1932 }
1933 }
1934
1935 // Filter out the caller activity if so requested.
1936 if (caller != null) {
1937 N = results.size();
1938 for (int i=0; i<N; i++) {
1939 ActivityInfo ainfo = results.get(i).activityInfo;
1940 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1941 && caller.getClassName().equals(ainfo.name)) {
1942 results.remove(i);
1943 break;
1944 }
1945 }
1946 }
1947
1948 // If the caller didn't request filter information,
1949 // drop them now so we don't have to
1950 // marshall/unmarshall it.
1951 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1952 N = results.size();
1953 for (int i=0; i<N; i++) {
1954 results.get(i).filter = null;
1955 }
1956 }
1957
1958 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1959 return results;
1960 }
1961
1962 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1963 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001964 ComponentName comp = intent.getComponent();
1965 if (comp != null) {
1966 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1967 ActivityInfo ai = getReceiverInfo(comp, flags);
1968 if (ai != null) {
1969 ResolveInfo ri = new ResolveInfo();
1970 ri.activityInfo = ai;
1971 list.add(ri);
1972 }
1973 return list;
1974 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001977 String pkgName = intent.getPackage();
1978 if (pkgName == null) {
1979 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1980 resolvedType, flags);
1981 }
1982 PackageParser.Package pkg = mPackages.get(pkgName);
1983 if (pkg != null) {
1984 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1985 resolvedType, flags, pkg.receivers);
1986 }
1987 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 }
1989 }
1990
1991 public ResolveInfo resolveService(Intent intent, String resolvedType,
1992 int flags) {
1993 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1994 flags);
1995 if (query != null) {
1996 if (query.size() >= 1) {
1997 // If there is more than one service with the same priority,
1998 // just arbitrarily pick the first one.
1999 return query.get(0);
2000 }
2001 }
2002 return null;
2003 }
2004
2005 public List<ResolveInfo> queryIntentServices(Intent intent,
2006 String resolvedType, int flags) {
2007 ComponentName comp = intent.getComponent();
2008 if (comp != null) {
2009 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2010 ServiceInfo si = getServiceInfo(comp, flags);
2011 if (si != null) {
2012 ResolveInfo ri = new ResolveInfo();
2013 ri.serviceInfo = si;
2014 list.add(ri);
2015 }
2016 return list;
2017 }
2018
2019 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002020 String pkgName = intent.getPackage();
2021 if (pkgName == null) {
2022 return (List<ResolveInfo>)mServices.queryIntent(intent,
2023 resolvedType, flags);
2024 }
2025 PackageParser.Package pkg = mPackages.get(pkgName);
2026 if (pkg != null) {
2027 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
2028 resolvedType, flags, pkg.services);
2029 }
2030 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 }
2032 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 public List<PackageInfo> getInstalledPackages(int flags) {
2035 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2036
2037 synchronized (mPackages) {
2038 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2039 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2040 while (i.hasNext()) {
2041 final PackageSetting ps = i.next();
2042 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2043 if(psPkg != null) {
2044 finalList.add(psPkg);
2045 }
2046 }
2047 }
2048 else {
2049 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2050 while (i.hasNext()) {
2051 final PackageParser.Package p = i.next();
2052 if (p.applicationInfo != null) {
2053 PackageInfo pi = generatePackageInfo(p, flags);
2054 if(pi != null) {
2055 finalList.add(pi);
2056 }
2057 }
2058 }
2059 }
2060 }
2061 return finalList;
2062 }
2063
2064 public List<ApplicationInfo> getInstalledApplications(int flags) {
2065 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2066 synchronized(mPackages) {
2067 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2068 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2069 while (i.hasNext()) {
2070 final PackageSetting ps = i.next();
2071 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2072 if(ai != null) {
2073 finalList.add(ai);
2074 }
2075 }
2076 }
2077 else {
2078 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2079 while (i.hasNext()) {
2080 final PackageParser.Package p = i.next();
2081 if (p.applicationInfo != null) {
2082 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2083 if(ai != null) {
2084 finalList.add(ai);
2085 }
2086 }
2087 }
2088 }
2089 }
2090 return finalList;
2091 }
2092
2093 public List<ApplicationInfo> getPersistentApplications(int flags) {
2094 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2095
2096 synchronized (mPackages) {
2097 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2098 while (i.hasNext()) {
2099 PackageParser.Package p = i.next();
2100 if (p.applicationInfo != null
2101 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
2102 && (!mSafeMode || (p.applicationInfo.flags
2103 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2104 finalList.add(p.applicationInfo);
2105 }
2106 }
2107 }
2108
2109 return finalList;
2110 }
2111
2112 public ProviderInfo resolveContentProvider(String name, int flags) {
2113 synchronized (mPackages) {
2114 final PackageParser.Provider provider = mProviders.get(name);
2115 return provider != null
2116 && mSettings.isEnabledLP(provider.info, flags)
2117 && (!mSafeMode || (provider.info.applicationInfo.flags
2118 &ApplicationInfo.FLAG_SYSTEM) != 0)
2119 ? PackageParser.generateProviderInfo(provider, flags)
2120 : null;
2121 }
2122 }
2123
Fred Quintana718d8a22009-04-29 17:53:20 -07002124 /**
2125 * @deprecated
2126 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 public void querySyncProviders(List outNames, List outInfo) {
2128 synchronized (mPackages) {
2129 Iterator<Map.Entry<String, PackageParser.Provider>> i
2130 = mProviders.entrySet().iterator();
2131
2132 while (i.hasNext()) {
2133 Map.Entry<String, PackageParser.Provider> entry = i.next();
2134 PackageParser.Provider p = entry.getValue();
2135
2136 if (p.syncable
2137 && (!mSafeMode || (p.info.applicationInfo.flags
2138 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2139 outNames.add(entry.getKey());
2140 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2141 }
2142 }
2143 }
2144 }
2145
2146 public List<ProviderInfo> queryContentProviders(String processName,
2147 int uid, int flags) {
2148 ArrayList<ProviderInfo> finalList = null;
2149
2150 synchronized (mPackages) {
2151 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2152 while (i.hasNext()) {
2153 PackageParser.Provider p = i.next();
2154 if (p.info.authority != null
2155 && (processName == null ||
2156 (p.info.processName.equals(processName)
2157 && p.info.applicationInfo.uid == uid))
2158 && mSettings.isEnabledLP(p.info, flags)
2159 && (!mSafeMode || (p.info.applicationInfo.flags
2160 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2161 if (finalList == null) {
2162 finalList = new ArrayList<ProviderInfo>(3);
2163 }
2164 finalList.add(PackageParser.generateProviderInfo(p,
2165 flags));
2166 }
2167 }
2168 }
2169
2170 if (finalList != null) {
2171 Collections.sort(finalList, mProviderInitOrderSorter);
2172 }
2173
2174 return finalList;
2175 }
2176
2177 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2178 int flags) {
2179 synchronized (mPackages) {
2180 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2181 return PackageParser.generateInstrumentationInfo(i, flags);
2182 }
2183 }
2184
2185 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2186 int flags) {
2187 ArrayList<InstrumentationInfo> finalList =
2188 new ArrayList<InstrumentationInfo>();
2189
2190 synchronized (mPackages) {
2191 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2192 while (i.hasNext()) {
2193 PackageParser.Instrumentation p = i.next();
2194 if (targetPackage == null
2195 || targetPackage.equals(p.info.targetPackage)) {
2196 finalList.add(PackageParser.generateInstrumentationInfo(p,
2197 flags));
2198 }
2199 }
2200 }
2201
2202 return finalList;
2203 }
2204
2205 private void scanDirLI(File dir, int flags, int scanMode) {
2206 Log.d(TAG, "Scanning app dir " + dir);
2207
2208 String[] files = dir.list();
2209
2210 int i;
2211 for (i=0; i<files.length; i++) {
2212 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002213 if (!isPackageFilename(files[i])) {
2214 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002215 continue;
2216 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002217 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002219 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002220 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2221 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002222 // Delete the apk
2223 Log.w(TAG, "Cleaning up failed install of " + file);
2224 file.delete();
2225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227 }
2228
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002229 private static File getSettingsProblemFile() {
2230 File dataDir = Environment.getDataDirectory();
2231 File systemDir = new File(dataDir, "system");
2232 File fname = new File(systemDir, "uiderrors.txt");
2233 return fname;
2234 }
2235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 private static void reportSettingsProblem(int priority, String msg) {
2237 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002238 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 FileOutputStream out = new FileOutputStream(fname, true);
2240 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002241 SimpleDateFormat formatter = new SimpleDateFormat();
2242 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2243 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 pw.close();
2245 FileUtils.setPermissions(
2246 fname.toString(),
2247 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2248 -1, -1);
2249 } catch (java.io.IOException e) {
2250 }
2251 Log.println(priority, TAG, msg);
2252 }
2253
2254 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2255 PackageParser.Package pkg, File srcFile, int parseFlags) {
2256 if (GET_CERTIFICATES) {
2257 if (ps == null || !ps.codePath.equals(srcFile)
2258 || ps.getTimeStamp() != srcFile.lastModified()) {
2259 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2260 if (!pp.collectCertificates(pkg, parseFlags)) {
2261 mLastScanError = pp.getParseError();
2262 return false;
2263 }
2264 }
2265 }
2266 return true;
2267 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 /*
2270 * Scan a package and return the newly parsed package.
2271 * Returns null in case of errors and the error code is stored in mLastScanError
2272 */
2273 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002274 int parseFlags, int scanMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002276 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002278 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002281 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 if (pkg == null) {
2283 mLastScanError = pp.getParseError();
2284 return null;
2285 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002286 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 PackageSetting updatedPkg;
2288 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002289 // Look to see if we already know about this package.
2290 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
2291 if (oldName != null && oldName.equals(pkg.mOriginalPackage)) {
2292 // This package has been renamed to its original name. Let's
2293 // use that.
2294 ps = mSettings.peekPackageLP(pkg.mOriginalPackage);
2295 }
2296 // If there was no original package, see one for the real package name.
2297 if (ps == null) {
2298 ps = mSettings.peekPackageLP(pkg.packageName);
2299 }
2300 // Check to see if this package could be hiding/updating a system
2301 // package. Must look for it either under the original or real
2302 // package name depending on our state.
2303 updatedPkg = mSettings.mDisabledSysPackages.get(
2304 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002306 // First check if this is a system package that may involve an update
2307 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2308 if (!ps.codePath.equals(scanFile)) {
2309 // The path has changed from what was last scanned... check the
2310 // version of the new path against what we have stored to determine
2311 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002312 if (pkg.mVersionCode < ps.versionCode) {
2313 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002314 // Ignore entry. Skip it.
2315 Log.i(TAG, "Package " + ps.name + " at " + scanFile
2316 + "ignored: updated version " + ps.versionCode
2317 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002318 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2319 return null;
2320 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002321 // The current app on the system partion is better than
2322 // what we have updated to on the data partition; switch
2323 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002324 // At this point, its safely assumed that package installation for
2325 // apps in system partition will go through. If not there won't be a working
2326 // version of the app
2327 synchronized (mPackages) {
2328 // Just remove the loaded entries from package lists.
2329 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002330 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002331 Log.w(TAG, "Package " + ps.name + " at " + scanFile
2332 + "reverting from " + ps.codePathString
2333 + ": new version " + pkg.mVersionCode
2334 + " better than installed " + ps.versionCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002335 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2336 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002337 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 }
2340 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002341 if (updatedPkg != null) {
2342 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2343 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2344 }
2345 // Verify certificates against what was last scanned
2346 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2347 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2348 return null;
2349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 // The apk is forward locked (not public) if its code and resources
2351 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002352 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002354 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002355 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002356
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002357 String codePath = null;
2358 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002359 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2360 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002361 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002362 } else {
2363 // Should not happen at all. Just log an error.
2364 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2365 }
2366 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002367 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002368 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002369 codePath = pkg.mScanPath;
2370 // Set application objects path explicitly.
2371 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002373 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 }
2375
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002376 private static void setApplicationInfoPaths(PackageParser.Package pkg,
2377 String destCodePath, String destResPath) {
2378 pkg.mPath = pkg.mScanPath = destCodePath;
2379 pkg.applicationInfo.sourceDir = destCodePath;
2380 pkg.applicationInfo.publicSourceDir = destResPath;
2381 }
2382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 private static String fixProcessName(String defProcessName,
2384 String processName, int uid) {
2385 if (processName == null) {
2386 return defProcessName;
2387 }
2388 return processName;
2389 }
2390
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002391 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002392 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2393 if (pkg.mSignatures != null) {
2394 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2395 updateSignature)) {
2396 Log.e(TAG, "Package " + pkg.packageName
2397 + " signatures do not match the previously installed version; ignoring!");
2398 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2399 return false;
2400 }
2401
2402 if (pkgSetting.sharedUser != null) {
2403 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2404 pkg.mSignatures, updateSignature)) {
2405 Log.e(TAG, "Package " + pkg.packageName
2406 + " has no signatures that match those in shared user "
2407 + pkgSetting.sharedUser.name + "; ignoring!");
2408 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2409 return false;
2410 }
2411 }
2412 } else {
2413 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2414 }
2415 return true;
2416 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002417
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002418 public boolean performDexOpt(String packageName) {
2419 if (!mNoDexOpt) {
2420 return false;
2421 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002422
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002423 PackageParser.Package p;
2424 synchronized (mPackages) {
2425 p = mPackages.get(packageName);
2426 if (p == null || p.mDidDexOpt) {
2427 return false;
2428 }
2429 }
2430 synchronized (mInstallLock) {
2431 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2432 }
2433 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002434
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002435 static final int DEX_OPT_SKIPPED = 0;
2436 static final int DEX_OPT_PERFORMED = 1;
2437 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002438
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002439 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2440 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002441 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002442 String path = pkg.mScanPath;
2443 int ret = 0;
2444 try {
2445 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002446 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002447 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002448 pkg.mDidDexOpt = true;
2449 performed = true;
2450 }
2451 } catch (FileNotFoundException e) {
2452 Log.w(TAG, "Apk not found for dexopt: " + path);
2453 ret = -1;
2454 } catch (IOException e) {
2455 Log.w(TAG, "Exception reading apk: " + path, e);
2456 ret = -1;
2457 }
2458 if (ret < 0) {
2459 //error from installer
2460 return DEX_OPT_FAILED;
2461 }
2462 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002463
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002464 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2465 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002466
2467 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2468 return Environment.isEncryptedFilesystemEnabled() &&
2469 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2470 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002471
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002472 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2473 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2474 Log.w(TAG, "Unable to update from " + oldPkg.name
2475 + " to " + newPkg.packageName
2476 + ": old package not in system partition");
2477 return false;
2478 } else if (mPackages.get(oldPkg.name) != null) {
2479 Log.w(TAG, "Unable to update from " + oldPkg.name
2480 + " to " + newPkg.packageName
2481 + ": old package still exists");
2482 return false;
2483 }
2484 return true;
2485 }
2486
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002487 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
2488 int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002489 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002490 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2491 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002492 // Bail out. The resource and code paths haven't been set.
2493 Log.w(TAG, " Code and resource paths haven't been set correctly");
2494 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2495 return null;
2496 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 mScanningPath = scanFile;
2498 if (pkg == null) {
2499 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2500 return null;
2501 }
2502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2504 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2505 }
2506
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002507 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 synchronized (mPackages) {
2509 if (mAndroidApplication != null) {
2510 Log.w(TAG, "*************************************************");
2511 Log.w(TAG, "Core android package being redefined. Skipping.");
2512 Log.w(TAG, " file=" + mScanningPath);
2513 Log.w(TAG, "*************************************************");
2514 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2515 return null;
2516 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 // Set up information for our fall-back user intent resolution
2519 // activity.
2520 mPlatformPackage = pkg;
2521 pkg.mVersionCode = mSdkVersion;
2522 mAndroidApplication = pkg.applicationInfo;
2523 mResolveActivity.applicationInfo = mAndroidApplication;
2524 mResolveActivity.name = ResolverActivity.class.getName();
2525 mResolveActivity.packageName = mAndroidApplication.packageName;
2526 mResolveActivity.processName = mAndroidApplication.processName;
2527 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2528 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2529 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2530 mResolveActivity.exported = true;
2531 mResolveActivity.enabled = true;
2532 mResolveInfo.activityInfo = mResolveActivity;
2533 mResolveInfo.priority = 0;
2534 mResolveInfo.preferredOrder = 0;
2535 mResolveInfo.match = 0;
2536 mResolveComponentName = new ComponentName(
2537 mAndroidApplication.packageName, mResolveActivity.name);
2538 }
2539 }
2540
2541 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002542 TAG, "Scanning package " + pkg.packageName);
2543 if (mPackages.containsKey(pkg.packageName)
2544 || mSharedLibraries.containsKey(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 Log.w(TAG, "*************************************************");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002546 Log.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 + " already installed. Skipping duplicate.");
2548 Log.w(TAG, "*************************************************");
2549 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2550 return null;
2551 }
2552
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002553 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002554 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2555 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 SharedUserSetting suid = null;
2558 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002561
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002562 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2563 // Only system apps can use these features.
2564 pkg.mOriginalPackage = null;
2565 pkg.mRealPackage = null;
2566 pkg.mAdoptPermissions = null;
2567 }
2568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 synchronized (mPackages) {
2570 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002571 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2572 if (mTmpSharedLibraries == null ||
2573 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2574 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2575 }
2576 int num = 0;
2577 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2578 for (int i=0; i<N; i++) {
2579 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 if (file == null) {
2581 Log.e(TAG, "Package " + pkg.packageName
2582 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002583 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002584 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2585 return null;
2586 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002587 mTmpSharedLibraries[num] = file;
2588 num++;
2589 }
2590 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2591 for (int i=0; i<N; i++) {
2592 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2593 if (file == null) {
2594 Log.w(TAG, "Package " + pkg.packageName
2595 + " desires unavailable shared library "
2596 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2597 } else {
2598 mTmpSharedLibraries[num] = file;
2599 num++;
2600 }
2601 }
2602 if (num > 0) {
2603 pkg.usesLibraryFiles = new String[num];
2604 System.arraycopy(mTmpSharedLibraries, 0,
2605 pkg.usesLibraryFiles, 0, num);
2606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002607
Dianne Hackborn49237342009-08-27 20:08:01 -07002608 if (pkg.reqFeatures != null) {
2609 N = pkg.reqFeatures.size();
2610 for (int i=0; i<N; i++) {
2611 FeatureInfo fi = pkg.reqFeatures.get(i);
2612 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2613 // Don't care.
2614 continue;
2615 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002616
Dianne Hackborn49237342009-08-27 20:08:01 -07002617 if (fi.name != null) {
2618 if (mAvailableFeatures.get(fi.name) == null) {
2619 Log.e(TAG, "Package " + pkg.packageName
2620 + " requires unavailable feature "
2621 + fi.name + "; failing!");
2622 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2623 return null;
2624 }
2625 }
2626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002627 }
2628 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 if (pkg.mSharedUserId != null) {
2631 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2632 pkg.applicationInfo.flags, true);
2633 if (suid == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002634 Log.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 + " for shared user failed");
2636 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2637 return null;
2638 }
2639 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2640 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2641 + suid.userId + "): packages=" + suid.packages);
2642 }
2643 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002644
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002645 if (false) {
2646 if (pkg.mOriginalPackage != null) {
2647 Log.w(TAG, "WAITING FOR DEBUGGER");
2648 Debug.waitForDebugger();
2649 Log.i(TAG, "Package " + pkg.packageName + " from original package"
2650 + pkg.mOriginalPackage);
2651 }
2652 }
2653
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002654 // Check if we are renaming from an original package name.
2655 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002656 String realName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002657 if (pkg.mOriginalPackage != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002658 // This package may need to be renamed to a previously
2659 // installed name. Let's check on that...
2660 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
2661 if (pkg.mOriginalPackage.equals(renamed)) {
2662 // This package had originally been installed as the
2663 // original name, and we have already taken care of
2664 // transitioning to the new one. Just update the new
2665 // one to continue using the old name.
2666 realName = pkg.mRealPackage;
2667 if (!pkg.packageName.equals(renamed)) {
2668 // Callers into this function may have already taken
2669 // care of renaming the package; only do it here if
2670 // it is not already done.
2671 pkg.setPackageName(renamed);
2672 }
2673
2674 } else if ((origPackage
2675 = mSettings.peekPackageLP(pkg.mOriginalPackage)) != null) {
2676 // We do have the package already installed under its
2677 // original name... should we use it?
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002678 if (!verifyPackageUpdate(origPackage, pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002679 // New package is not compatible with original.
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002680 origPackage = null;
2681 } else if (origPackage.sharedUser != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002682 // Make sure uid is compatible between packages.
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002683 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
2684 Log.w(TAG, "Unable to migrate data from " + origPackage.name
2685 + " to " + pkg.packageName + ": old uid "
2686 + origPackage.sharedUser.name
2687 + " differs from " + pkg.mSharedUserId);
2688 origPackage = null;
2689 }
2690 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002691 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
2692 + pkg.packageName + " to old name " + origPackage.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002693 }
2694 }
2695 }
2696
2697 if (mTransferedPackages.contains(pkg.packageName)) {
2698 Log.w(TAG, "Package " + pkg.packageName
2699 + " was transferred to another, but its .apk remains");
2700 }
2701
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002702 // Just create the setting, don't add it yet. For already existing packages
2703 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002704 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 destResourceFile, pkg.applicationInfo.flags, true, false);
2706 if (pkgSetting == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002707 Log.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2709 return null;
2710 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002711
2712 if (pkgSetting.origPackage != null) {
2713 // If we are first transitioning from an original package,
2714 // fix up the new package's name now. We need to do this after
2715 // looking up the package under its new name, so getPackageLP
2716 // can take care of fiddling things correctly.
2717 pkg.setPackageName(origPackage.name);
2718
2719 // File a report about this.
2720 String msg = "New package " + pkgSetting.realName
2721 + " renamed to replace old package " + pkgSetting.name;
2722 reportSettingsProblem(Log.WARN, msg);
2723
2724 // Make a note of it.
2725 mTransferedPackages.add(origPackage.name);
2726
2727 // No longer need to retain this.
2728 pkgSetting.origPackage = null;
2729 }
2730
2731 if (realName != null) {
2732 // Make a note of it.
2733 mTransferedPackages.add(pkg.packageName);
2734 }
2735
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002736 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 pkg.applicationInfo.uid = pkgSetting.userId;
2741 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002742
2743 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2745 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2746 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2747 return null;
2748 }
2749 // The signature has changed, but this package is in the system
2750 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002751 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 // However... if this package is part of a shared user, but it
2753 // doesn't match the signature of the shared user, let's fail.
2754 // What this means is that you can't change the signatures
2755 // associated with an overall shared user, which doesn't seem all
2756 // that unreasonable.
2757 if (pkgSetting.sharedUser != null) {
2758 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2759 pkg.mSignatures, false)) {
2760 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2761 return null;
2762 }
2763 }
2764 removeExisting = true;
2765 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002766
The Android Open Source Project10592532009-03-18 17:39:46 -07002767 // Verify that this new package doesn't have any content providers
2768 // that conflict with existing packages. Only do this if the
2769 // package isn't already installed, since we don't want to break
2770 // things that are installed.
2771 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2772 int N = pkg.providers.size();
2773 int i;
2774 for (i=0; i<N; i++) {
2775 PackageParser.Provider p = pkg.providers.get(i);
2776 String names[] = p.info.authority.split(";");
2777 for (int j = 0; j < names.length; j++) {
2778 if (mProviders.containsKey(names[j])) {
2779 PackageParser.Provider other = mProviders.get(names[j]);
2780 Log.w(TAG, "Can't install because provider name " + names[j] +
2781 " (in package " + pkg.applicationInfo.packageName +
2782 ") is already used by "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002783 + ((other != null && other.getComponentName() != null)
2784 ? other.getComponentName().getPackageName() : "?"));
The Android Open Source Project10592532009-03-18 17:39:46 -07002785 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2786 return null;
2787 }
2788 }
2789 }
2790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 }
2792
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002793 final String pkgName = pkg.packageName;
2794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002796 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002797 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002798 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 if (ret != 0) {
2800 String msg = "System package " + pkg.packageName
2801 + " could not have data directory erased after signature change.";
2802 reportSettingsProblem(Log.WARN, msg);
2803 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2804 return null;
2805 }
2806 }
2807 Log.w(TAG, "System package " + pkg.packageName
2808 + " signature changed: existing data removed.");
2809 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2810 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002811
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002812 if (pkg.mAdoptPermissions != null) {
2813 // This package wants to adopt ownership of permissions from
2814 // another package.
2815 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
2816 String origName = pkg.mAdoptPermissions.get(i);
2817 PackageSetting orig = mSettings.peekPackageLP(origName);
2818 if (orig != null) {
2819 if (verifyPackageUpdate(orig, pkg)) {
2820 Log.i(TAG, "Adopting permissions from "
2821 + origName + " to " + pkg.packageName);
2822 mSettings.transferPermissions(origName, pkg.packageName);
2823 }
2824 }
2825 }
2826 }
2827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 long scanFileTime = scanFile.lastModified();
2829 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2830 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2831 pkg.applicationInfo.processName = fixProcessName(
2832 pkg.applicationInfo.packageName,
2833 pkg.applicationInfo.processName,
2834 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835
2836 File dataPath;
2837 if (mPlatformPackage == pkg) {
2838 // The system package is special.
2839 dataPath = new File (Environment.getDataDirectory(), "system");
2840 pkg.applicationInfo.dataDir = dataPath.getPath();
2841 } else {
2842 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002843 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2844 if (useEncryptedFSDir) {
2845 dataPath = new File(mSecureAppDataDir, pkgName);
2846 } else {
2847 dataPath = new File(mAppDataDir, pkgName);
2848 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002849
2850 boolean uidError = false;
2851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 if (dataPath.exists()) {
2853 mOutPermissions[1] = 0;
2854 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2855 if (mOutPermissions[1] == pkg.applicationInfo.uid
2856 || !Process.supportsProcesses()) {
2857 pkg.applicationInfo.dataDir = dataPath.getPath();
2858 } else {
2859 boolean recovered = false;
2860 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2861 // If this is a system app, we can at least delete its
2862 // current data so the application will still work.
2863 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002864 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002865 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 // Old data gone!
2867 String msg = "System package " + pkg.packageName
2868 + " has changed from uid: "
2869 + mOutPermissions[1] + " to "
2870 + pkg.applicationInfo.uid + "; old data erased";
2871 reportSettingsProblem(Log.WARN, msg);
2872 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002875 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 pkg.applicationInfo.uid);
2877 if (ret == -1) {
2878 // Ack should not happen!
2879 msg = "System package " + pkg.packageName
2880 + " could not have data directory re-created after delete.";
2881 reportSettingsProblem(Log.WARN, msg);
2882 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2883 return null;
2884 }
2885 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 if (!recovered) {
2888 mHasSystemUidErrors = true;
2889 }
2890 }
2891 if (!recovered) {
2892 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2893 + pkg.applicationInfo.uid + "/fs_"
2894 + mOutPermissions[1];
2895 String msg = "Package " + pkg.packageName
2896 + " has mismatched uid: "
2897 + mOutPermissions[1] + " on disk, "
2898 + pkg.applicationInfo.uid + " in settings";
2899 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002900 mSettings.mReadMessages.append(msg);
2901 mSettings.mReadMessages.append('\n');
2902 uidError = true;
2903 if (!pkgSetting.uidError) {
2904 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002906 }
2907 }
2908 }
2909 pkg.applicationInfo.dataDir = dataPath.getPath();
2910 } else {
2911 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2912 Log.v(TAG, "Want this data dir: " + dataPath);
2913 //invoke installer to do the actual installation
2914 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002915 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002916 pkg.applicationInfo.uid);
2917 if(ret < 0) {
2918 // Error from installer
2919 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2920 return null;
2921 }
2922 } else {
2923 dataPath.mkdirs();
2924 if (dataPath.exists()) {
2925 FileUtils.setPermissions(
2926 dataPath.toString(),
2927 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2928 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2929 }
2930 }
2931 if (dataPath.exists()) {
2932 pkg.applicationInfo.dataDir = dataPath.getPath();
2933 } else {
2934 Log.w(TAG, "Unable to create data directory: " + dataPath);
2935 pkg.applicationInfo.dataDir = null;
2936 }
2937 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002938
2939 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
2941
2942 // Perform shared library installation and dex validation and
2943 // optimization, if this is not a system app.
2944 if (mInstaller != null) {
2945 String path = scanFile.getPath();
2946 if (scanFileNewer) {
2947 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002948 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2949 if (err != PackageManager.INSTALL_SUCCEEDED) {
2950 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 return null;
2952 }
2953 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002954 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002955
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002956 if ((scanMode&SCAN_NO_DEX) == 0) {
2957 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2959 return null;
2960 }
2961 }
2962 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 if (mFactoryTest && pkg.requestedPermissions.contains(
2965 android.Manifest.permission.FACTORY_TEST)) {
2966 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2967 }
2968
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002969 // Request the ActivityManager to kill the process(only for existing packages)
2970 // so that we do not end up in a confused state while the user is still using the older
2971 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002972 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002973 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002974 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002975 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002977 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002978 // We don't expect installation to fail beyond this point,
2979 if ((scanMode&SCAN_MONITOR) != 0) {
2980 mAppDirs.put(pkg.mPath, pkg);
2981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002983 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002985 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08002986 // Make sure we don't accidentally delete its data.
2987 mSettings.mPackagesToBeCleaned.remove(pkgName);
2988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 int N = pkg.providers.size();
2990 StringBuilder r = null;
2991 int i;
2992 for (i=0; i<N; i++) {
2993 PackageParser.Provider p = pkg.providers.get(i);
2994 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2995 p.info.processName, pkg.applicationInfo.uid);
2996 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2997 p.info.name), p);
2998 p.syncable = p.info.isSyncable;
2999 String names[] = p.info.authority.split(";");
3000 p.info.authority = null;
3001 for (int j = 0; j < names.length; j++) {
3002 if (j == 1 && p.syncable) {
3003 // We only want the first authority for a provider to possibly be
3004 // syncable, so if we already added this provider using a different
3005 // authority clear the syncable flag. We copy the provider before
3006 // changing it because the mProviders object contains a reference
3007 // to a provider that we don't want to change.
3008 // Only do this for the second authority since the resulting provider
3009 // object can be the same for all future authorities for this provider.
3010 p = new PackageParser.Provider(p);
3011 p.syncable = false;
3012 }
3013 if (!mProviders.containsKey(names[j])) {
3014 mProviders.put(names[j], p);
3015 if (p.info.authority == null) {
3016 p.info.authority = names[j];
3017 } else {
3018 p.info.authority = p.info.authority + ";" + names[j];
3019 }
3020 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
3021 Log.d(TAG, "Registered content provider: " + names[j] +
3022 ", className = " + p.info.name +
3023 ", isSyncable = " + p.info.isSyncable);
3024 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07003025 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 Log.w(TAG, "Skipping provider name " + names[j] +
3027 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07003028 "): name already used by "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003029 + ((other != null && other.getComponentName() != null)
3030 ? other.getComponentName().getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 }
3032 }
3033 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3034 if (r == null) {
3035 r = new StringBuilder(256);
3036 } else {
3037 r.append(' ');
3038 }
3039 r.append(p.info.name);
3040 }
3041 }
3042 if (r != null) {
3043 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3044 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 N = pkg.services.size();
3047 r = null;
3048 for (i=0; i<N; i++) {
3049 PackageParser.Service s = pkg.services.get(i);
3050 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3051 s.info.processName, pkg.applicationInfo.uid);
3052 mServices.addService(s);
3053 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3054 if (r == null) {
3055 r = new StringBuilder(256);
3056 } else {
3057 r.append(' ');
3058 }
3059 r.append(s.info.name);
3060 }
3061 }
3062 if (r != null) {
3063 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3064 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 N = pkg.receivers.size();
3067 r = null;
3068 for (i=0; i<N; i++) {
3069 PackageParser.Activity a = pkg.receivers.get(i);
3070 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3071 a.info.processName, pkg.applicationInfo.uid);
3072 mReceivers.addActivity(a, "receiver");
3073 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3074 if (r == null) {
3075 r = new StringBuilder(256);
3076 } else {
3077 r.append(' ');
3078 }
3079 r.append(a.info.name);
3080 }
3081 }
3082 if (r != null) {
3083 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3084 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 N = pkg.activities.size();
3087 r = null;
3088 for (i=0; i<N; i++) {
3089 PackageParser.Activity a = pkg.activities.get(i);
3090 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3091 a.info.processName, pkg.applicationInfo.uid);
3092 mActivities.addActivity(a, "activity");
3093 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3094 if (r == null) {
3095 r = new StringBuilder(256);
3096 } else {
3097 r.append(' ');
3098 }
3099 r.append(a.info.name);
3100 }
3101 }
3102 if (r != null) {
3103 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3104 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003106 N = pkg.permissionGroups.size();
3107 r = null;
3108 for (i=0; i<N; i++) {
3109 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3110 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3111 if (cur == null) {
3112 mPermissionGroups.put(pg.info.name, pg);
3113 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3114 if (r == null) {
3115 r = new StringBuilder(256);
3116 } else {
3117 r.append(' ');
3118 }
3119 r.append(pg.info.name);
3120 }
3121 } else {
3122 Log.w(TAG, "Permission group " + pg.info.name + " from package "
3123 + pg.info.packageName + " ignored: original from "
3124 + cur.info.packageName);
3125 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3126 if (r == null) {
3127 r = new StringBuilder(256);
3128 } else {
3129 r.append(' ');
3130 }
3131 r.append("DUP:");
3132 r.append(pg.info.name);
3133 }
3134 }
3135 }
3136 if (r != null) {
3137 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3138 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 N = pkg.permissions.size();
3141 r = null;
3142 for (i=0; i<N; i++) {
3143 PackageParser.Permission p = pkg.permissions.get(i);
3144 HashMap<String, BasePermission> permissionMap =
3145 p.tree ? mSettings.mPermissionTrees
3146 : mSettings.mPermissions;
3147 p.group = mPermissionGroups.get(p.info.group);
3148 if (p.info.group == null || p.group != null) {
3149 BasePermission bp = permissionMap.get(p.info.name);
3150 if (bp == null) {
3151 bp = new BasePermission(p.info.name, p.info.packageName,
3152 BasePermission.TYPE_NORMAL);
3153 permissionMap.put(p.info.name, bp);
3154 }
3155 if (bp.perm == null) {
3156 if (bp.sourcePackage == null
3157 || bp.sourcePackage.equals(p.info.packageName)) {
3158 BasePermission tree = findPermissionTreeLP(p.info.name);
3159 if (tree == null
3160 || tree.sourcePackage.equals(p.info.packageName)) {
3161 bp.perm = p;
3162 bp.uid = pkg.applicationInfo.uid;
3163 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3164 if (r == null) {
3165 r = new StringBuilder(256);
3166 } else {
3167 r.append(' ');
3168 }
3169 r.append(p.info.name);
3170 }
3171 } else {
3172 Log.w(TAG, "Permission " + p.info.name + " from package "
3173 + p.info.packageName + " ignored: base tree "
3174 + tree.name + " is from package "
3175 + tree.sourcePackage);
3176 }
3177 } else {
3178 Log.w(TAG, "Permission " + p.info.name + " from package "
3179 + p.info.packageName + " ignored: original from "
3180 + bp.sourcePackage);
3181 }
3182 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3183 if (r == null) {
3184 r = new StringBuilder(256);
3185 } else {
3186 r.append(' ');
3187 }
3188 r.append("DUP:");
3189 r.append(p.info.name);
3190 }
3191 } else {
3192 Log.w(TAG, "Permission " + p.info.name + " from package "
3193 + p.info.packageName + " ignored: no group "
3194 + p.group);
3195 }
3196 }
3197 if (r != null) {
3198 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3199 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 N = pkg.instrumentation.size();
3202 r = null;
3203 for (i=0; i<N; i++) {
3204 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3205 a.info.packageName = pkg.applicationInfo.packageName;
3206 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3207 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3208 a.info.dataDir = pkg.applicationInfo.dataDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003209 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3211 if (r == null) {
3212 r = new StringBuilder(256);
3213 } else {
3214 r.append(' ');
3215 }
3216 r.append(a.info.name);
3217 }
3218 }
3219 if (r != null) {
3220 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3221 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003222
Dianne Hackborn854060af2009-07-09 18:14:31 -07003223 if (pkg.protectedBroadcasts != null) {
3224 N = pkg.protectedBroadcasts.size();
3225 for (i=0; i<N; i++) {
3226 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3227 }
3228 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003230 pkgSetting.setTimeStamp(scanFileTime);
3231 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 return pkg;
3234 }
3235
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003236 private void killApplication(String pkgName, int uid) {
3237 // Request the ActivityManager to kill the process(only for existing packages)
3238 // so that we do not end up in a confused state while the user is still using the older
3239 // version of the application while the new one gets installed.
3240 IActivityManager am = ActivityManagerNative.getDefault();
3241 if (am != null) {
3242 try {
3243 am.killApplicationWithUid(pkgName, uid);
3244 } catch (RemoteException e) {
3245 }
3246 }
3247 }
3248
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003249 // The following constants are returned by cachePackageSharedLibsForAbiLI
3250 // to indicate if native shared libraries were found in the package.
3251 // Values are:
3252 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
3253 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
3254 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
3255 // in package (and not installed)
3256 //
3257 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
3258 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
3259 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003261 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
3262 // and automatically copy them to /data/data/<appname>/lib if present.
3263 //
3264 // NOTE: this method may throw an IOException if the library cannot
3265 // be copied to its final destination, e.g. if there isn't enough
3266 // room left on the data partition, or a ZipException if the package
3267 // file is malformed.
3268 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003269 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
3270 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003271 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
3272 final String apkLib = "lib/";
3273 final int apkLibLen = apkLib.length();
3274 final int cpuAbiLen = cpuAbi.length();
3275 final String libPrefix = "lib";
3276 final int libPrefixLen = libPrefix.length();
3277 final String libSuffix = ".so";
3278 final int libSuffixLen = libSuffix.length();
3279 boolean hasNativeLibraries = false;
3280 boolean installedNativeLibraries = false;
3281
3282 // the minimum length of a valid native shared library of the form
3283 // lib/<something>/lib<name>.so.
3284 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
3285
3286 ZipFile zipFile = new ZipFile(scanFile);
3287 Enumeration<ZipEntry> entries =
3288 (Enumeration<ZipEntry>) zipFile.entries();
3289
3290 while (entries.hasMoreElements()) {
3291 ZipEntry entry = entries.nextElement();
3292 // skip directories
3293 if (entry.isDirectory()) {
3294 continue;
3295 }
3296 String entryName = entry.getName();
3297
3298 // check that the entry looks like lib/<something>/lib<name>.so
3299 // here, but don't check the ABI just yet.
3300 //
3301 // - must be sufficiently long
3302 // - must end with libSuffix, i.e. ".so"
3303 // - must start with apkLib, i.e. "lib/"
3304 if (entryName.length() < minEntryLen ||
3305 !entryName.endsWith(libSuffix) ||
3306 !entryName.startsWith(apkLib) ) {
3307 continue;
3308 }
3309
3310 // file name must start with libPrefix, i.e. "lib"
3311 int lastSlash = entryName.lastIndexOf('/');
3312
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003313 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003314 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
3315 continue;
3316 }
3317
3318 hasNativeLibraries = true;
3319
3320 // check the cpuAbi now, between lib/ and /lib<name>.so
3321 //
3322 if (lastSlash != apkLibLen + cpuAbiLen ||
3323 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3324 continue;
3325
3326 // extract the library file name, ensure it doesn't contain
3327 // weird characters. we're guaranteed here that it doesn't contain
3328 // a directory separator though.
3329 String libFileName = entryName.substring(lastSlash+1);
3330 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3331 continue;
3332 }
3333
3334 installedNativeLibraries = true;
3335
3336 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3337 File.separator + libFileName;
3338 File sharedLibraryFile = new File(sharedLibraryFilePath);
3339 if (! sharedLibraryFile.exists() ||
3340 sharedLibraryFile.length() != entry.getSize() ||
3341 sharedLibraryFile.lastModified() != entry.getTime()) {
3342 if (Config.LOGD) {
3343 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003345 if (mInstaller == null) {
3346 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003347 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003348 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003349 sharedLibraryFile);
3350 }
3351 }
3352 if (!hasNativeLibraries)
3353 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3354
3355 if (!installedNativeLibraries)
3356 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3357
3358 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3359 }
3360
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003361 // Find the gdbserver executable program in a package at
3362 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3363 //
3364 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3365 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3366 //
3367 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3368 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3369 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3370 final String GDBSERVER = "gdbserver";
3371 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3372
3373 ZipFile zipFile = new ZipFile(scanFile);
3374 Enumeration<ZipEntry> entries =
3375 (Enumeration<ZipEntry>) zipFile.entries();
3376
3377 while (entries.hasMoreElements()) {
3378 ZipEntry entry = entries.nextElement();
3379 // skip directories
3380 if (entry.isDirectory()) {
3381 continue;
3382 }
3383 String entryName = entry.getName();
3384
3385 if (!entryName.equals(apkGdbServerPath)) {
3386 continue;
3387 }
3388
3389 String installGdbServerPath = installGdbServerDir.getPath() +
3390 "/" + GDBSERVER;
3391 File installGdbServerFile = new File(installGdbServerPath);
3392 if (! installGdbServerFile.exists() ||
3393 installGdbServerFile.length() != entry.getSize() ||
3394 installGdbServerFile.lastModified() != entry.getTime()) {
3395 if (Config.LOGD) {
3396 Log.d(TAG, "Caching gdbserver " + entry.getName());
3397 }
3398 if (mInstaller == null) {
3399 installGdbServerDir.mkdir();
3400 }
3401 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3402 installGdbServerFile);
3403 }
3404 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3405 }
3406 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3407 }
3408
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003409 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3410 // and copy them to /data/data/<appname>/lib.
3411 //
3412 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3413 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3414 // one if ro.product.cpu.abi2 is defined.
3415 //
3416 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3417 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003418 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003419 try {
3420 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3421
3422 // some architectures are capable of supporting several CPU ABIs
3423 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3424 // this is indicated by the definition of the ro.product.cpu.abi2
3425 // system property.
3426 //
3427 // only scan the package twice in case of ABI mismatch
3428 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003429 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003430 if (cpuAbi2 != null) {
3431 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003433
3434 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3435 Log.w(TAG,"Native ABI mismatch from package file");
3436 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003438
3439 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3440 cpuAbi = cpuAbi2;
3441 }
3442 }
3443
3444 // for debuggable packages, also extract gdbserver from lib/<abi>
3445 // into /data/data/<appname>/lib too.
3446 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3447 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3448 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3449 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3450 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003452 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003453 } catch (ZipException e) {
3454 Log.w(TAG, "Failed to extract data from package file", e);
3455 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003457 Log.w(TAG, "Failed to cache package shared libs", e);
3458 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003460 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 }
3462
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003463 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003465 File binaryDir,
3466 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 InputStream inputStream = zipFile.getInputStream(entry);
3468 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003469 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003471 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003472 // now need to be left as world readable and owned by the system.
3473 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3474 ! tempFile.setLastModified(entry.getTime()) ||
3475 FileUtils.setPermissions(tempFilePath,
3476 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003477 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003479 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 // Failed to properly write file.
3481 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003482 throw new IOException("Couldn't create cached binary "
3483 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 }
3485 } finally {
3486 inputStream.close();
3487 }
3488 }
3489
3490 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3491 if (chatty && Config.LOGD) Log.d(
3492 TAG, "Removing package " + pkg.applicationInfo.packageName );
3493
3494 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003495 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003497 mPackages.remove(pkg.applicationInfo.packageName);
3498 if (pkg.mPath != null) {
3499 mAppDirs.remove(pkg.mPath);
3500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 PackageSetting ps = (PackageSetting)pkg.mExtras;
3503 if (ps != null && ps.sharedUser != null) {
3504 // XXX don't do this until the data is removed.
3505 if (false) {
3506 ps.sharedUser.packages.remove(ps);
3507 if (ps.sharedUser.packages.size() == 0) {
3508 // Remove.
3509 }
3510 }
3511 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 int N = pkg.providers.size();
3514 StringBuilder r = null;
3515 int i;
3516 for (i=0; i<N; i++) {
3517 PackageParser.Provider p = pkg.providers.get(i);
3518 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3519 p.info.name));
3520 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 /* The is another ContentProvider with this authority when
3523 * this app was installed so this authority is null,
3524 * Ignore it as we don't have to unregister the provider.
3525 */
3526 continue;
3527 }
3528 String names[] = p.info.authority.split(";");
3529 for (int j = 0; j < names.length; j++) {
3530 if (mProviders.get(names[j]) == p) {
3531 mProviders.remove(names[j]);
3532 if (chatty && Config.LOGD) Log.d(
3533 TAG, "Unregistered content provider: " + names[j] +
3534 ", className = " + p.info.name +
3535 ", isSyncable = " + p.info.isSyncable);
3536 }
3537 }
3538 if (chatty) {
3539 if (r == null) {
3540 r = new StringBuilder(256);
3541 } else {
3542 r.append(' ');
3543 }
3544 r.append(p.info.name);
3545 }
3546 }
3547 if (r != null) {
3548 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3549 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 N = pkg.services.size();
3552 r = null;
3553 for (i=0; i<N; i++) {
3554 PackageParser.Service s = pkg.services.get(i);
3555 mServices.removeService(s);
3556 if (chatty) {
3557 if (r == null) {
3558 r = new StringBuilder(256);
3559 } else {
3560 r.append(' ');
3561 }
3562 r.append(s.info.name);
3563 }
3564 }
3565 if (r != null) {
3566 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3567 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003569 N = pkg.receivers.size();
3570 r = null;
3571 for (i=0; i<N; i++) {
3572 PackageParser.Activity a = pkg.receivers.get(i);
3573 mReceivers.removeActivity(a, "receiver");
3574 if (chatty) {
3575 if (r == null) {
3576 r = new StringBuilder(256);
3577 } else {
3578 r.append(' ');
3579 }
3580 r.append(a.info.name);
3581 }
3582 }
3583 if (r != null) {
3584 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 N = pkg.activities.size();
3588 r = null;
3589 for (i=0; i<N; i++) {
3590 PackageParser.Activity a = pkg.activities.get(i);
3591 mActivities.removeActivity(a, "activity");
3592 if (chatty) {
3593 if (r == null) {
3594 r = new StringBuilder(256);
3595 } else {
3596 r.append(' ');
3597 }
3598 r.append(a.info.name);
3599 }
3600 }
3601 if (r != null) {
3602 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3603 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 N = pkg.permissions.size();
3606 r = null;
3607 for (i=0; i<N; i++) {
3608 PackageParser.Permission p = pkg.permissions.get(i);
3609 boolean tree = false;
3610 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3611 if (bp == null) {
3612 tree = true;
3613 bp = mSettings.mPermissionTrees.get(p.info.name);
3614 }
3615 if (bp != null && bp.perm == p) {
3616 if (bp.type != BasePermission.TYPE_BUILTIN) {
3617 if (tree) {
3618 mSettings.mPermissionTrees.remove(p.info.name);
3619 } else {
3620 mSettings.mPermissions.remove(p.info.name);
3621 }
3622 } else {
3623 bp.perm = null;
3624 }
3625 if (chatty) {
3626 if (r == null) {
3627 r = new StringBuilder(256);
3628 } else {
3629 r.append(' ');
3630 }
3631 r.append(p.info.name);
3632 }
3633 }
3634 }
3635 if (r != null) {
3636 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3637 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 N = pkg.instrumentation.size();
3640 r = null;
3641 for (i=0; i<N; i++) {
3642 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003643 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 if (chatty) {
3645 if (r == null) {
3646 r = new StringBuilder(256);
3647 } else {
3648 r.append(' ');
3649 }
3650 r.append(a.info.name);
3651 }
3652 }
3653 if (r != null) {
3654 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3655 }
3656 }
3657 }
3658
3659 private static final boolean isPackageFilename(String name) {
3660 return name != null && name.endsWith(".apk");
3661 }
3662
3663 private void updatePermissionsLP() {
3664 // Make sure there are no dangling permission trees.
3665 Iterator<BasePermission> it = mSettings.mPermissionTrees
3666 .values().iterator();
3667 while (it.hasNext()) {
3668 BasePermission bp = it.next();
3669 if (bp.perm == null) {
3670 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3671 + " from package " + bp.sourcePackage);
3672 it.remove();
3673 }
3674 }
3675
3676 // Make sure all dynamic permissions have been assigned to a package,
3677 // and make sure there are no dangling permissions.
3678 it = mSettings.mPermissions.values().iterator();
3679 while (it.hasNext()) {
3680 BasePermission bp = it.next();
3681 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3682 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3683 + bp.name + " pkg=" + bp.sourcePackage
3684 + " info=" + bp.pendingInfo);
3685 if (bp.perm == null && bp.pendingInfo != null) {
3686 BasePermission tree = findPermissionTreeLP(bp.name);
3687 if (tree != null) {
3688 bp.perm = new PackageParser.Permission(tree.perm.owner,
3689 new PermissionInfo(bp.pendingInfo));
3690 bp.perm.info.packageName = tree.perm.info.packageName;
3691 bp.perm.info.name = bp.name;
3692 bp.uid = tree.uid;
3693 }
3694 }
3695 }
3696 if (bp.perm == null) {
3697 Log.w(TAG, "Removing dangling permission: " + bp.name
3698 + " from package " + bp.sourcePackage);
3699 it.remove();
3700 }
3701 }
3702
3703 // Now update the permissions for all packages, in particular
3704 // replace the granted permissions of the system packages.
3705 for (PackageParser.Package pkg : mPackages.values()) {
3706 grantPermissionsLP(pkg, false);
3707 }
3708 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3711 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3712 if (ps == null) {
3713 return;
3714 }
3715 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3716 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 if (replace) {
3719 ps.permissionsFixed = false;
3720 if (gp == ps) {
3721 gp.grantedPermissions.clear();
3722 gp.gids = mGlobalGids;
3723 }
3724 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 if (gp.gids == null) {
3727 gp.gids = mGlobalGids;
3728 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003730 final int N = pkg.requestedPermissions.size();
3731 for (int i=0; i<N; i++) {
3732 String name = pkg.requestedPermissions.get(i);
3733 BasePermission bp = mSettings.mPermissions.get(name);
3734 PackageParser.Permission p = bp != null ? bp.perm : null;
3735 if (false) {
3736 if (gp != ps) {
3737 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3738 + ": " + p);
3739 }
3740 }
3741 if (p != null) {
3742 final String perm = p.info.name;
3743 boolean allowed;
3744 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3745 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3746 allowed = true;
3747 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3748 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003749 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003751 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 == PackageManager.SIGNATURE_MATCH);
3753 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3754 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3755 // For updated system applications, the signatureOrSystem permission
3756 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003757 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003758 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3759 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3760 if(sysPs.grantedPermissions.contains(perm)) {
3761 allowed = true;
3762 } else {
3763 allowed = false;
3764 }
3765 } else {
3766 allowed = true;
3767 }
3768 }
3769 }
3770 } else {
3771 allowed = false;
3772 }
3773 if (false) {
3774 if (gp != ps) {
3775 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3776 }
3777 }
3778 if (allowed) {
3779 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3780 && ps.permissionsFixed) {
3781 // If this is an existing, non-system package, then
3782 // we can't add any new permissions to it.
3783 if (!gp.loadedPermissions.contains(perm)) {
3784 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003785 // Except... if this is a permission that was added
3786 // to the platform (note: need to only do this when
3787 // updating the platform).
3788 final int NP = PackageParser.NEW_PERMISSIONS.length;
3789 for (int ip=0; ip<NP; ip++) {
3790 final PackageParser.NewPermissionInfo npi
3791 = PackageParser.NEW_PERMISSIONS[ip];
3792 if (npi.name.equals(perm)
3793 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3794 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003795 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003796 + pkg.packageName);
3797 break;
3798 }
3799 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 }
3801 }
3802 if (allowed) {
3803 if (!gp.grantedPermissions.contains(perm)) {
3804 addedPermission = true;
3805 gp.grantedPermissions.add(perm);
3806 gp.gids = appendInts(gp.gids, bp.gids);
3807 }
3808 } else {
3809 Log.w(TAG, "Not granting permission " + perm
3810 + " to package " + pkg.packageName
3811 + " because it was previously installed without");
3812 }
3813 } else {
3814 Log.w(TAG, "Not granting permission " + perm
3815 + " to package " + pkg.packageName
3816 + " (protectionLevel=" + p.info.protectionLevel
3817 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3818 + ")");
3819 }
3820 } else {
3821 Log.w(TAG, "Unknown permission " + name
3822 + " in package " + pkg.packageName);
3823 }
3824 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003826 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003827 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3828 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 // This is the first that we have heard about this package, so the
3830 // permissions we have now selected are fixed until explicitly
3831 // changed.
3832 ps.permissionsFixed = true;
3833 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3834 }
3835 }
3836
3837 private final class ActivityIntentResolver
3838 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003839 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003841 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 }
3843
Mihai Preda074edef2009-05-18 17:13:31 +02003844 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003846 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3848 }
3849
Mihai Predaeae850c2009-05-13 10:13:48 +02003850 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3851 ArrayList<PackageParser.Activity> packageActivities) {
3852 if (packageActivities == null) {
3853 return null;
3854 }
3855 mFlags = flags;
3856 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3857 int N = packageActivities.size();
3858 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3859 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003860
3861 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003862 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003863 intentFilters = packageActivities.get(i).intents;
3864 if (intentFilters != null && intentFilters.size() > 0) {
3865 listCut.add(intentFilters);
3866 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003867 }
3868 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3869 }
3870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 public final void addActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003872 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 if (SHOW_INFO || Config.LOGV) Log.v(
3874 TAG, " " + type + " " +
3875 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3876 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3877 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003878 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3880 if (SHOW_INFO || Config.LOGV) {
3881 Log.v(TAG, " IntentFilter:");
3882 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3883 }
3884 if (!intent.debugCheck()) {
3885 Log.w(TAG, "==> For Activity " + a.info.name);
3886 }
3887 addFilter(intent);
3888 }
3889 }
3890
3891 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003892 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 if (SHOW_INFO || Config.LOGV) Log.v(
3894 TAG, " " + type + " " +
3895 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3896 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3897 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003898 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3900 if (SHOW_INFO || Config.LOGV) {
3901 Log.v(TAG, " IntentFilter:");
3902 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3903 }
3904 removeFilter(intent);
3905 }
3906 }
3907
3908 @Override
3909 protected boolean allowFilterResult(
3910 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3911 ActivityInfo filterAi = filter.activity.info;
3912 for (int i=dest.size()-1; i>=0; i--) {
3913 ActivityInfo destAi = dest.get(i).activityInfo;
3914 if (destAi.name == filterAi.name
3915 && destAi.packageName == filterAi.packageName) {
3916 return false;
3917 }
3918 }
3919 return true;
3920 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 @Override
3923 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3924 int match) {
3925 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3926 return null;
3927 }
3928 final PackageParser.Activity activity = info.activity;
3929 if (mSafeMode && (activity.info.applicationInfo.flags
3930 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3931 return null;
3932 }
3933 final ResolveInfo res = new ResolveInfo();
3934 res.activityInfo = PackageParser.generateActivityInfo(activity,
3935 mFlags);
3936 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3937 res.filter = info;
3938 }
3939 res.priority = info.getPriority();
3940 res.preferredOrder = activity.owner.mPreferredOrder;
3941 //System.out.println("Result: " + res.activityInfo.className +
3942 // " = " + res.priority);
3943 res.match = match;
3944 res.isDefault = info.hasDefault;
3945 res.labelRes = info.labelRes;
3946 res.nonLocalizedLabel = info.nonLocalizedLabel;
3947 res.icon = info.icon;
3948 return res;
3949 }
3950
3951 @Override
3952 protected void sortResults(List<ResolveInfo> results) {
3953 Collections.sort(results, mResolvePrioritySorter);
3954 }
3955
3956 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003957 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003959 out.print(prefix); out.print(
3960 Integer.toHexString(System.identityHashCode(filter.activity)));
3961 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003962 out.println(filter.activity.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 }
3964
3965// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3966// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3967// final List<ResolveInfo> retList = Lists.newArrayList();
3968// while (i.hasNext()) {
3969// final ResolveInfo resolveInfo = i.next();
3970// if (isEnabledLP(resolveInfo.activityInfo)) {
3971// retList.add(resolveInfo);
3972// }
3973// }
3974// return retList;
3975// }
3976
3977 // Keys are String (activity class name), values are Activity.
3978 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3979 = new HashMap<ComponentName, PackageParser.Activity>();
3980 private int mFlags;
3981 }
3982
3983 private final class ServiceIntentResolver
3984 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003985 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003987 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 }
3989
Mihai Preda074edef2009-05-18 17:13:31 +02003990 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003992 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3994 }
3995
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003996 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3997 ArrayList<PackageParser.Service> packageServices) {
3998 if (packageServices == null) {
3999 return null;
4000 }
4001 mFlags = flags;
4002 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4003 int N = packageServices.size();
4004 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4005 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4006
4007 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4008 for (int i = 0; i < N; ++i) {
4009 intentFilters = packageServices.get(i).intents;
4010 if (intentFilters != null && intentFilters.size() > 0) {
4011 listCut.add(intentFilters);
4012 }
4013 }
4014 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4015 }
4016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004018 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 if (SHOW_INFO || Config.LOGV) Log.v(
4020 TAG, " " + (s.info.nonLocalizedLabel != null
4021 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4022 if (SHOW_INFO || Config.LOGV) Log.v(
4023 TAG, " Class=" + s.info.name);
4024 int NI = s.intents.size();
4025 int j;
4026 for (j=0; j<NI; j++) {
4027 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4028 if (SHOW_INFO || Config.LOGV) {
4029 Log.v(TAG, " IntentFilter:");
4030 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4031 }
4032 if (!intent.debugCheck()) {
4033 Log.w(TAG, "==> For Service " + s.info.name);
4034 }
4035 addFilter(intent);
4036 }
4037 }
4038
4039 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004040 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 if (SHOW_INFO || Config.LOGV) Log.v(
4042 TAG, " " + (s.info.nonLocalizedLabel != null
4043 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4044 if (SHOW_INFO || Config.LOGV) Log.v(
4045 TAG, " Class=" + s.info.name);
4046 int NI = s.intents.size();
4047 int j;
4048 for (j=0; j<NI; j++) {
4049 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4050 if (SHOW_INFO || Config.LOGV) {
4051 Log.v(TAG, " IntentFilter:");
4052 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4053 }
4054 removeFilter(intent);
4055 }
4056 }
4057
4058 @Override
4059 protected boolean allowFilterResult(
4060 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4061 ServiceInfo filterSi = filter.service.info;
4062 for (int i=dest.size()-1; i>=0; i--) {
4063 ServiceInfo destAi = dest.get(i).serviceInfo;
4064 if (destAi.name == filterSi.name
4065 && destAi.packageName == filterSi.packageName) {
4066 return false;
4067 }
4068 }
4069 return true;
4070 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 @Override
4073 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4074 int match) {
4075 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
4076 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4077 return null;
4078 }
4079 final PackageParser.Service service = info.service;
4080 if (mSafeMode && (service.info.applicationInfo.flags
4081 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4082 return null;
4083 }
4084 final ResolveInfo res = new ResolveInfo();
4085 res.serviceInfo = PackageParser.generateServiceInfo(service,
4086 mFlags);
4087 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4088 res.filter = filter;
4089 }
4090 res.priority = info.getPriority();
4091 res.preferredOrder = service.owner.mPreferredOrder;
4092 //System.out.println("Result: " + res.activityInfo.className +
4093 // " = " + res.priority);
4094 res.match = match;
4095 res.isDefault = info.hasDefault;
4096 res.labelRes = info.labelRes;
4097 res.nonLocalizedLabel = info.nonLocalizedLabel;
4098 res.icon = info.icon;
4099 return res;
4100 }
4101
4102 @Override
4103 protected void sortResults(List<ResolveInfo> results) {
4104 Collections.sort(results, mResolvePrioritySorter);
4105 }
4106
4107 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004108 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004110 out.print(prefix); out.print(
4111 Integer.toHexString(System.identityHashCode(filter.service)));
4112 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004113 out.println(filter.service.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 }
4115
4116// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4117// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4118// final List<ResolveInfo> retList = Lists.newArrayList();
4119// while (i.hasNext()) {
4120// final ResolveInfo resolveInfo = (ResolveInfo) i;
4121// if (isEnabledLP(resolveInfo.serviceInfo)) {
4122// retList.add(resolveInfo);
4123// }
4124// }
4125// return retList;
4126// }
4127
4128 // Keys are String (activity class name), values are Activity.
4129 private final HashMap<ComponentName, PackageParser.Service> mServices
4130 = new HashMap<ComponentName, PackageParser.Service>();
4131 private int mFlags;
4132 };
4133
4134 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4135 new Comparator<ResolveInfo>() {
4136 public int compare(ResolveInfo r1, ResolveInfo r2) {
4137 int v1 = r1.priority;
4138 int v2 = r2.priority;
4139 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4140 if (v1 != v2) {
4141 return (v1 > v2) ? -1 : 1;
4142 }
4143 v1 = r1.preferredOrder;
4144 v2 = r2.preferredOrder;
4145 if (v1 != v2) {
4146 return (v1 > v2) ? -1 : 1;
4147 }
4148 if (r1.isDefault != r2.isDefault) {
4149 return r1.isDefault ? -1 : 1;
4150 }
4151 v1 = r1.match;
4152 v2 = r2.match;
4153 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4154 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4155 }
4156 };
4157
4158 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4159 new Comparator<ProviderInfo>() {
4160 public int compare(ProviderInfo p1, ProviderInfo p2) {
4161 final int v1 = p1.initOrder;
4162 final int v2 = p2.initOrder;
4163 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4164 }
4165 };
4166
4167 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
4168 IActivityManager am = ActivityManagerNative.getDefault();
4169 if (am != null) {
4170 try {
4171 final Intent intent = new Intent(action,
4172 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4173 if (extras != null) {
4174 intent.putExtras(extras);
4175 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004176 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 am.broadcastIntent(
4178 null, intent,
4179 null, null, 0, null, null, null, false, false);
4180 } catch (RemoteException ex) {
4181 }
4182 }
4183 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004184
4185 public String nextPackageToClean(String lastPackage) {
4186 synchronized (mPackages) {
4187 if (!mMediaMounted) {
4188 // If the external storage is no longer mounted at this point,
4189 // the caller may not have been able to delete all of this
4190 // packages files and can not delete any more. Bail.
4191 return null;
4192 }
4193 if (lastPackage != null) {
4194 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4195 }
4196 return mSettings.mPackagesToBeCleaned.size() > 0
4197 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4198 }
4199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004201 void schedulePackageCleaning(String packageName) {
4202 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4203 }
4204
4205 void startCleaningPackages() {
4206 synchronized (mPackages) {
4207 if (!mMediaMounted) {
4208 return;
4209 }
4210 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4211 return;
4212 }
4213 }
4214 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4215 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4216 IActivityManager am = ActivityManagerNative.getDefault();
4217 if (am != null) {
4218 try {
4219 am.startService(null, intent, null);
4220 } catch (RemoteException e) {
4221 }
4222 }
4223 }
4224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 private final class AppDirObserver extends FileObserver {
4226 public AppDirObserver(String path, int mask, boolean isrom) {
4227 super(path, mask);
4228 mRootDir = path;
4229 mIsRom = isrom;
4230 }
4231
4232 public void onEvent(int event, String path) {
4233 String removedPackage = null;
4234 int removedUid = -1;
4235 String addedPackage = null;
4236 int addedUid = -1;
4237
4238 synchronized (mInstallLock) {
4239 String fullPathStr = null;
4240 File fullPath = null;
4241 if (path != null) {
4242 fullPath = new File(mRootDir, path);
4243 fullPathStr = fullPath.getPath();
4244 }
4245
4246 if (Config.LOGV) Log.v(
4247 TAG, "File " + fullPathStr + " changed: "
4248 + Integer.toHexString(event));
4249
4250 if (!isPackageFilename(path)) {
4251 if (Config.LOGV) Log.v(
4252 TAG, "Ignoring change of non-package file: " + fullPathStr);
4253 return;
4254 }
4255
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004256 // Ignore packages that are being installed or
4257 // have just been installed.
4258 if (ignoreCodePath(fullPathStr)) {
4259 return;
4260 }
4261 PackageParser.Package p = null;
4262 synchronized (mPackages) {
4263 p = mAppDirs.get(fullPathStr);
4264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004266 if (p != null) {
4267 removePackageLI(p, true);
4268 removedPackage = p.applicationInfo.packageName;
4269 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004270 }
4271 }
4272
4273 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004275 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004276 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
4277 PackageParser.PARSE_CHATTY |
4278 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08004279 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 if (p != null) {
4281 synchronized (mPackages) {
4282 grantPermissionsLP(p, false);
4283 }
4284 addedPackage = p.applicationInfo.packageName;
4285 addedUid = p.applicationInfo.uid;
4286 }
4287 }
4288 }
4289
4290 synchronized (mPackages) {
4291 mSettings.writeLP();
4292 }
4293 }
4294
4295 if (removedPackage != null) {
4296 Bundle extras = new Bundle(1);
4297 extras.putInt(Intent.EXTRA_UID, removedUid);
4298 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4299 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4300 }
4301 if (addedPackage != null) {
4302 Bundle extras = new Bundle(1);
4303 extras.putInt(Intent.EXTRA_UID, addedUid);
4304 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
4305 }
4306 }
4307
4308 private final String mRootDir;
4309 private final boolean mIsRom;
4310 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004312 /* Called when a downloaded package installation has been confirmed by the user */
4313 public void installPackage(
4314 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004315 installPackage(packageURI, observer, flags, null);
4316 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004317
Jacek Surazski65e13172009-04-28 15:26:38 +02004318 /* Called when a downloaded package installation has been confirmed by the user */
4319 public void installPackage(
4320 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4321 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 mContext.enforceCallingOrSelfPermission(
4323 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004324
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004325 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004326 msg.obj = new InstallParams(packageURI, observer, flags,
4327 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004328 mHandler.sendMessage(msg);
4329 }
4330
Christopher Tate1bb69062010-02-19 17:02:12 -08004331 public void finishPackageInstall(int token) {
4332 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4333 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4334 mHandler.sendMessage(msg);
4335 }
4336
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004337 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 // Queue up an async operation since the package installation may take a little while.
4339 mHandler.post(new Runnable() {
4340 public void run() {
4341 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004342 // Result object to be returned
4343 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004344 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004345 res.uid = -1;
4346 res.pkg = null;
4347 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004348 args.doPreInstall(res.returnCode);
4349 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004350 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004351 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004352 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004353 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004354 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004355
4356 // A restore should be performed at this point if (a) the install
4357 // succeeded, (b) the operation is not an update, and (c) the new
4358 // package has a backupAgent defined.
4359 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004360 boolean doRestore = (!update
4361 && res.pkg != null
4362 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004363
4364 // Set up the post-install work request bookkeeping. This will be used
4365 // and cleaned up by the post-install event handling regardless of whether
4366 // there's a restore pass performed. Token values are >= 1.
4367 int token;
4368 if (mNextInstallToken < 0) mNextInstallToken = 1;
4369 token = mNextInstallToken++;
4370
4371 PostInstallData data = new PostInstallData(args, res);
4372 mRunningInstalls.put(token, data);
4373 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4374
4375 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4376 // Pass responsibility to the Backup Manager. It will perform a
4377 // restore if appropriate, then pass responsibility back to the
4378 // Package Manager to run the post-install observer callbacks
4379 // and broadcasts.
4380 IBackupManager bm = IBackupManager.Stub.asInterface(
4381 ServiceManager.getService(Context.BACKUP_SERVICE));
4382 if (bm != null) {
4383 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4384 + " to BM for possible restore");
4385 try {
4386 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4387 } catch (RemoteException e) {
4388 // can't happen; the backup manager is local
4389 } catch (Exception e) {
4390 Log.e(TAG, "Exception trying to enqueue restore", e);
4391 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004392 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004393 } else {
4394 Log.e(TAG, "Backup Manager not found!");
4395 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004398
4399 if (!doRestore) {
4400 // No restore possible, or the Backup Manager was mysteriously not
4401 // available -- just fire the post-install work request directly.
4402 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4403 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4404 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004405 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
4407 });
4408 }
4409
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004410 interface HandlerParams {
4411 void handleStartCopy(IMediaContainerService imcs);
4412 void handleServiceError();
4413 }
4414
4415 class InstallParams implements HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004416 final IPackageInstallObserver observer;
4417 int flags;
4418 final Uri packageURI;
4419 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004420 private InstallArgs mArgs;
4421 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004422 InstallParams(Uri packageURI,
4423 IPackageInstallObserver observer, int flags,
4424 String installerPackageName) {
4425 this.packageURI = packageURI;
4426 this.flags = flags;
4427 this.observer = observer;
4428 this.installerPackageName = installerPackageName;
4429 }
4430
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004431 private int getInstallLocation(IMediaContainerService imcs) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004432 try {
4433 return imcs.getRecommendedInstallLocation(packageURI);
4434 } catch (RemoteException e) {
4435 }
4436 return -1;
4437 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004438
4439 public void handleStartCopy(IMediaContainerService imcs) {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004440 int ret = PackageManager.INSTALL_SUCCEEDED;
4441 // Dont need to invoke getInstallLocation for forward locked apps.
4442 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4443 flags &= ~PackageManager.INSTALL_EXTERNAL;
4444 } else if (imcs != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004445 // Remote call to find out default install location
4446 int loc = getInstallLocation(imcs);
4447 // Use install location to create InstallArgs and temporary
4448 // install location
4449 if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
4450 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4451 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
4452 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
4453 } else {
4454 if ((flags & PackageManager.INSTALL_EXTERNAL) == 0){
4455 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
4456 // Set the flag to install on external media.
4457 flags |= PackageManager.INSTALL_EXTERNAL;
4458 } else {
4459 // Make sure the flag for installing on external
4460 // media is unset
4461 flags &= ~PackageManager.INSTALL_EXTERNAL;
4462 }
4463 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004464 }
4465 }
4466 // Create the file args now.
4467 mArgs = createInstallArgs(this);
4468 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4469 // Create copy only if we are not in an erroneous state.
4470 // Remote call to initiate copy using temporary file
4471 ret = mArgs.copyApk(imcs, true);
4472 }
4473 mRet = ret;
4474 mHandler.sendEmptyMessage(MCS_UNBIND);
4475 handleReturnCode();
4476 }
4477
4478 void handleReturnCode() {
4479 processPendingInstall(mArgs, mRet);
4480 }
4481
4482 public void handleServiceError() {
4483 mArgs = createInstallArgs(this);
4484 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4485 handleReturnCode();
4486 }
4487 };
4488
4489 /*
4490 * Utility class used in movePackage api.
4491 * srcArgs and targetArgs are not set for invalid flags and make
4492 * sure to do null checks when invoking methods on them.
4493 * We probably want to return ErrorPrams for both failed installs
4494 * and moves.
4495 */
4496 class MoveParams implements HandlerParams {
4497 final IPackageMoveObserver observer;
4498 final int flags;
4499 final String packageName;
4500 final InstallArgs srcArgs;
4501 final InstallArgs targetArgs;
4502 int mRet;
4503 MoveParams(InstallArgs srcArgs,
4504 IPackageMoveObserver observer,
4505 int flags, String packageName) {
4506 this.srcArgs = srcArgs;
4507 this.observer = observer;
4508 this.flags = flags;
4509 this.packageName = packageName;
4510 if (srcArgs != null) {
4511 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
4512 targetArgs = createInstallArgs(packageUri, flags, packageName);
4513 } else {
4514 targetArgs = null;
4515 }
4516 }
4517
4518 public void handleStartCopy(IMediaContainerService imcs) {
4519 // Create the file args now.
4520 mRet = targetArgs.copyApk(imcs, false);
4521 targetArgs.doPreInstall(mRet);
4522 mHandler.sendEmptyMessage(MCS_UNBIND);
4523 handleReturnCode();
4524 }
4525
4526 void handleReturnCode() {
4527 targetArgs.doPostInstall(mRet);
4528 // TODO invoke pending move
4529 processPendingMove(this, mRet);
4530 }
4531
4532 public void handleServiceError() {
4533 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
4534 handleReturnCode();
4535 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004536 };
4537
4538 private InstallArgs createInstallArgs(InstallParams params) {
4539 if (installOnSd(params.flags)) {
4540 return new SdInstallArgs(params);
4541 } else {
4542 return new FileInstallArgs(params);
4543 }
4544 }
4545
4546 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
4547 if (installOnSd(flags)) {
4548 return new SdInstallArgs(fullCodePath, fullResourcePath);
4549 } else {
4550 return new FileInstallArgs(fullCodePath, fullResourcePath);
4551 }
4552 }
4553
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004554 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName) {
4555 if (installOnSd(flags)) {
4556 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
4557 return new SdInstallArgs(packageURI, cid);
4558 } else {
4559 return new FileInstallArgs(packageURI, pkgName);
4560 }
4561 }
4562
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004563 static abstract class InstallArgs {
4564 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004565 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004566 final int flags;
4567 final Uri packageURI;
4568 final String installerPackageName;
4569
4570 InstallArgs(Uri packageURI,
4571 IPackageInstallObserver observer, int flags,
4572 String installerPackageName) {
4573 this.packageURI = packageURI;
4574 this.flags = flags;
4575 this.observer = observer;
4576 this.installerPackageName = installerPackageName;
4577 }
4578
4579 abstract void createCopyFile();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004580 abstract int copyApk(IMediaContainerService imcs, boolean temp);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004581 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004582 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004583 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004584 abstract String getCodePath();
4585 abstract String getResourcePath();
4586 // Need installer lock especially for dex file removal.
4587 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004588 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004589 }
4590
4591 class FileInstallArgs extends InstallArgs {
4592 File installDir;
4593 String codeFileName;
4594 String resourceFileName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004595 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004596
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004597 FileInstallArgs(InstallParams params) {
4598 super(params.packageURI, params.observer,
4599 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004600 }
4601
4602 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4603 super(null, null, 0, null);
4604 File codeFile = new File(fullCodePath);
4605 installDir = codeFile.getParentFile();
4606 codeFileName = fullCodePath;
4607 resourceFileName = fullResourcePath;
4608 }
4609
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004610 FileInstallArgs(Uri packageURI, String pkgName) {
4611 super(packageURI, null, 0, null);
4612 boolean fwdLocked = isFwdLocked(flags);
4613 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4614 String apkName = getNextCodePath(null, pkgName, ".apk");
4615 codeFileName = new File(installDir, apkName + ".apk").getPath();
4616 resourceFileName = getResourcePathFromCodePath();
4617 }
4618
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004619 String getCodePath() {
4620 return codeFileName;
4621 }
4622
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004623 void createCopyFile() {
4624 boolean fwdLocked = isFwdLocked(flags);
4625 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4626 codeFileName = createTempPackageFile(installDir).getPath();
4627 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004628 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004629 }
4630
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004631 int copyApk(IMediaContainerService imcs, boolean temp) {
4632 if (temp) {
4633 // Generate temp file name
4634 createCopyFile();
4635 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004636 // Get a ParcelFileDescriptor to write to the output file
4637 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004638 if (!created) {
4639 try {
4640 codeFile.createNewFile();
4641 // Set permissions
4642 if (!setPermissions()) {
4643 // Failed setting permissions.
4644 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4645 }
4646 } catch (IOException e) {
4647 Log.w(TAG, "Failed to create file " + codeFile);
4648 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4649 }
4650 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004651 ParcelFileDescriptor out = null;
4652 try {
4653 out = ParcelFileDescriptor.open(codeFile,
4654 ParcelFileDescriptor.MODE_READ_WRITE);
4655 } catch (FileNotFoundException e) {
4656 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4657 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4658 }
4659 // Copy the resource now
4660 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4661 try {
4662 if (imcs.copyResource(packageURI, out)) {
4663 ret = PackageManager.INSTALL_SUCCEEDED;
4664 }
4665 } catch (RemoteException e) {
4666 } finally {
4667 try { if (out != null) out.close(); } catch (IOException e) {}
4668 }
4669 return ret;
4670 }
4671
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004672 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004673 if (status != PackageManager.INSTALL_SUCCEEDED) {
4674 cleanUp();
4675 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004676 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004677 }
4678
4679 boolean doRename(int status, final String pkgName, String oldCodePath) {
4680 if (status != PackageManager.INSTALL_SUCCEEDED) {
4681 cleanUp();
4682 return false;
4683 } else {
4684 // Rename based on packageName
4685 File codeFile = new File(getCodePath());
4686 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4687 File desFile = new File(installDir, apkName + ".apk");
4688 if (!codeFile.renameTo(desFile)) {
4689 return false;
4690 }
4691 // Reset paths since the file has been renamed.
4692 codeFileName = desFile.getPath();
4693 resourceFileName = getResourcePathFromCodePath();
4694 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004695 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004696 // Failed setting permissions.
4697 return false;
4698 }
4699 return true;
4700 }
4701 }
4702
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004703 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004704 if (status != PackageManager.INSTALL_SUCCEEDED) {
4705 cleanUp();
4706 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004707 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004708 }
4709
4710 String getResourcePath() {
4711 return resourceFileName;
4712 }
4713
4714 String getResourcePathFromCodePath() {
4715 String codePath = getCodePath();
4716 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4717 String apkNameOnly = getApkName(codePath);
4718 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4719 } else {
4720 return codePath;
4721 }
4722 }
4723
4724 private boolean cleanUp() {
4725 boolean ret = true;
4726 String sourceDir = getCodePath();
4727 String publicSourceDir = getResourcePath();
4728 if (sourceDir != null) {
4729 File sourceFile = new File(sourceDir);
4730 if (!sourceFile.exists()) {
4731 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4732 ret = false;
4733 }
4734 // Delete application's code and resources
4735 sourceFile.delete();
4736 }
4737 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4738 final File publicSourceFile = new File(publicSourceDir);
4739 if (!publicSourceFile.exists()) {
4740 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4741 }
4742 if (publicSourceFile.exists()) {
4743 publicSourceFile.delete();
4744 }
4745 }
4746 return ret;
4747 }
4748
4749 void cleanUpResourcesLI() {
4750 String sourceDir = getCodePath();
4751 if (cleanUp() && mInstaller != null) {
4752 int retCode = mInstaller.rmdex(sourceDir);
4753 if (retCode < 0) {
4754 Log.w(TAG, "Couldn't remove dex file for package: "
4755 + " at location "
4756 + sourceDir + ", retcode=" + retCode);
4757 // we don't consider this to be a failure of the core package deletion
4758 }
4759 }
4760 }
4761
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004762 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004763 // TODO Do this in a more elegant way later on. for now just a hack
4764 if (!isFwdLocked(flags)) {
4765 final int filePermissions =
4766 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4767 |FileUtils.S_IROTH;
4768 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4769 if (retCode != 0) {
4770 Log.e(TAG, "Couldn't set new package file permissions for " +
4771 getCodePath()
4772 + ". The return code was: " + retCode);
4773 // TODO Define new internal error
4774 return false;
4775 }
4776 return true;
4777 }
4778 return true;
4779 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004780
4781 boolean doPostDeleteLI(boolean delete) {
4782 cleanUpResourcesLI();
4783 return true;
4784 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004785 }
4786
4787 class SdInstallArgs extends InstallArgs {
4788 String cid;
4789 String cachePath;
4790 static final String RES_FILE_NAME = "pkg.apk";
4791
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004792 SdInstallArgs(InstallParams params) {
4793 super(params.packageURI, params.observer,
4794 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004795 }
4796
4797 SdInstallArgs(String fullCodePath, String fullResourcePath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004798 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004799 // Extract cid from fullCodePath
4800 int eidx = fullCodePath.lastIndexOf("/");
4801 String subStr1 = fullCodePath.substring(0, eidx);
4802 int sidx = subStr1.lastIndexOf("/");
4803 cid = subStr1.substring(sidx+1, eidx);
4804 cachePath = subStr1;
4805 }
4806
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004807 SdInstallArgs(String cid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004808 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
4809 this.cid = cid;
4810 }
4811
4812 SdInstallArgs(Uri packageURI, String cid) {
4813 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004814 this.cid = cid;
4815 }
4816
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004817 void createCopyFile() {
4818 cid = getTempContainerId();
4819 }
4820
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004821 int copyApk(IMediaContainerService imcs, boolean temp) {
4822 if (temp) {
4823 createCopyFile();
4824 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004825 try {
4826 cachePath = imcs.copyResourceToContainer(
4827 packageURI, cid,
4828 getEncryptKey(), RES_FILE_NAME);
4829 } catch (RemoteException e) {
4830 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004831 return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
4832 PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004833 }
4834
4835 @Override
4836 String getCodePath() {
4837 return cachePath + "/" + RES_FILE_NAME;
4838 }
4839
4840 @Override
4841 String getResourcePath() {
4842 return cachePath + "/" + RES_FILE_NAME;
4843 }
4844
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004845 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004846 if (status != PackageManager.INSTALL_SUCCEEDED) {
4847 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004848 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004849 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004850 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004851 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004852 cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004853 if (cachePath == null) {
4854 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4855 }
4856 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004857 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004858 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004859 }
4860
4861 boolean doRename(int status, final String pkgName,
4862 String oldCodePath) {
4863 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004864 String newCachePath = null;
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08004865 boolean enableRename = false;
4866 if (enableRename) {
4867 if (PackageHelper.isContainerMounted(cid)) {
4868 // Unmount the container
4869 if (!PackageHelper.unMountSdDir(cid)) {
4870 Log.i(TAG, "Failed to unmount " + cid + " before renaming");
4871 return false;
4872 }
4873 }
4874 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
4875 Log.e(TAG, "Failed to rename " + cid + " to " + newCacheId);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004876 return false;
4877 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08004878 if (!PackageHelper.isContainerMounted(newCacheId)) {
4879 Log.w(TAG, "Mounting container " + newCacheId);
4880 newCachePath = PackageHelper.mountSdDir(newCacheId,
4881 getEncryptKey(), Process.SYSTEM_UID);
4882 } else {
4883 newCachePath = PackageHelper.getSdDir(newCacheId);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004884 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08004885 if (newCachePath == null) {
4886 Log.w(TAG, "Failed to get cache path for " + newCacheId);
4887 return false;
4888 }
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004889 // Mount old container?
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08004890 Log.i(TAG, "Succesfully renamed " + cid +
4891 " at path: " + cachePath + " to " + newCacheId +
4892 " at new path: " + newCachePath);
4893 cid = newCacheId;
4894 cachePath = newCachePath;
4895 return true;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004896 } else {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08004897 // STOPSHIP work around for rename
4898 Log.i(TAG, "Copying instead of renaming");
4899 File srcFile = new File(getCodePath());
4900 // Create new container
4901 newCachePath = PackageHelper.createSdDir(srcFile, newCacheId,
4902 getEncryptKey(), Process.SYSTEM_UID);
4903 Log.i(TAG, "Created rename container " + newCacheId);
4904 File destFile = new File(newCachePath + "/" + RES_FILE_NAME);
4905 if (!FileUtils.copyFile(srcFile, destFile)) {
4906 Log.e(TAG, "Failed to copy " + srcFile + " to " + destFile);
4907 return false;
4908 }
4909 Log.i(TAG, "Successfully copied resource to " + newCachePath);
4910 if (!PackageHelper.finalizeSdDir(newCacheId)) {
4911 Log.e(TAG, "Failed to finalize " + newCacheId);
4912 PackageHelper.destroySdDir(newCacheId);
4913 return false;
4914 }
4915 Log.i(TAG, "Finalized " + newCacheId);
4916 Runtime.getRuntime().gc();
4917 // Unmount first
4918 PackageHelper.unMountSdDir(cid);
4919 // Delete old container
4920 PackageHelper.destroySdDir(cid);
4921 // Dont have to mount. Already mounted.
4922 cid = newCacheId;
4923 cachePath = newCachePath;
4924 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004925 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004926 }
4927
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004928 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004929 if (status != PackageManager.INSTALL_SUCCEEDED) {
4930 cleanUp();
4931 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004932 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004933 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004934 PackageHelper.mountSdDir(cid,
4935 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004936 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004937 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004938 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004939 }
4940
4941 private void cleanUp() {
4942 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004943 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004944 }
4945
4946 void cleanUpResourcesLI() {
4947 String sourceFile = getCodePath();
4948 // Remove dex file
4949 if (mInstaller != null) {
4950 int retCode = mInstaller.rmdex(sourceFile.toString());
4951 if (retCode < 0) {
4952 Log.w(TAG, "Couldn't remove dex file for package: "
4953 + " at location "
4954 + sourceFile.toString() + ", retcode=" + retCode);
4955 // we don't consider this to be a failure of the core package deletion
4956 }
4957 }
4958 cleanUp();
4959 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004960
4961 boolean matchContainer(String app) {
4962 if (cid.startsWith(app)) {
4963 return true;
4964 }
4965 return false;
4966 }
4967
4968 String getPackageName() {
4969 int idx = cid.lastIndexOf("-");
4970 if (idx == -1) {
4971 return cid;
4972 }
4973 return cid.substring(0, idx);
4974 }
4975
4976 boolean doPostDeleteLI(boolean delete) {
4977 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004978 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004979 if (mounted) {
4980 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004981 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004982 }
4983 if (ret && delete) {
4984 cleanUpResourcesLI();
4985 }
4986 return ret;
4987 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004988 };
4989
4990 // Utility method used to create code paths based on package name and available index.
4991 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
4992 String idxStr = "";
4993 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004994 // Fall back to default value of idx=1 if prefix is not
4995 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004996 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004997 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004998 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004999 if (subStr.endsWith(suffix)) {
5000 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005001 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005002 // If oldCodePath already contains prefix find out the
5003 // ending index to either increment or decrement.
5004 int sidx = subStr.lastIndexOf(prefix);
5005 if (sidx != -1) {
5006 subStr = subStr.substring(sidx + prefix.length());
5007 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005008 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5009 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005010 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005011 try {
5012 idx = Integer.parseInt(subStr);
5013 if (idx <= 1) {
5014 idx++;
5015 } else {
5016 idx--;
5017 }
5018 } catch(NumberFormatException e) {
5019 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005020 }
5021 }
5022 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005023 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005024 return prefix + idxStr;
5025 }
5026
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005027 // Utility method used to ignore ADD/REMOVE events
5028 // by directory observer.
5029 private static boolean ignoreCodePath(String fullPathStr) {
5030 String apkName = getApkName(fullPathStr);
5031 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5032 if (idx != -1 && ((idx+1) < apkName.length())) {
5033 // Make sure the package ends with a numeral
5034 String version = apkName.substring(idx+1);
5035 try {
5036 Integer.parseInt(version);
5037 return true;
5038 } catch (NumberFormatException e) {}
5039 }
5040 return false;
5041 }
5042
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005043 // Utility method that returns the relative package path with respect
5044 // to the installation directory. Like say for /data/data/com.test-1.apk
5045 // string com.test-1 is returned.
5046 static String getApkName(String codePath) {
5047 if (codePath == null) {
5048 return null;
5049 }
5050 int sidx = codePath.lastIndexOf("/");
5051 int eidx = codePath.lastIndexOf(".");
5052 if (eidx == -1) {
5053 eidx = codePath.length();
5054 } else if (eidx == 0) {
5055 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
5056 return null;
5057 }
5058 return codePath.substring(sidx+1, eidx);
5059 }
5060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 class PackageInstalledInfo {
5062 String name;
5063 int uid;
5064 PackageParser.Package pkg;
5065 int returnCode;
5066 PackageRemovedInfo removedInfo;
5067 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005069 /*
5070 * Install a non-existing package.
5071 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005072 private void installNewPackageLI(PackageParser.Package pkg,
5073 int parseFlags,
5074 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005075 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08005077 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005078 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005079
5080 if (useEncryptedFilesystemForPackage(pkg)) {
5081 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
5082 } else {
5083 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
5084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 res.name = pkgName;
5086 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005087 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005089 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 + " without first uninstalling.");
5091 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5092 return;
5093 }
5094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005096 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005098 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5100 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5101 }
5102 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005103 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005104 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 res);
5106 // delete the partially installed application. the data directory will have to be
5107 // restored if it was already existing
5108 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5109 // remove package from internal structures. Note that we want deletePackageX to
5110 // delete the package data and cache directories that it created in
5111 // scanPackageLocked, unless those directories existed before we even tried to
5112 // install.
5113 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005114 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
5116 res.removedInfo);
5117 }
5118 }
5119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005120
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005121 private void replacePackageLI(PackageParser.Package pkg,
5122 int parseFlags,
5123 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005124 String installerPackageName, PackageInstalledInfo res) {
5125
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005126 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005127 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 // First find the old package info and check signatures
5129 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005130 oldPackage = mPackages.get(pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005131 if (checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005132 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5134 return;
5135 }
5136 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005137 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005138 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005139 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005141 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 }
5143 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005145 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005146 PackageParser.Package pkg,
5147 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005148 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005149 PackageParser.Package newPackage = null;
5150 String pkgName = deletedPackage.packageName;
5151 boolean deletedPkg = true;
5152 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005153
Jacek Surazski65e13172009-04-28 15:26:38 +02005154 String oldInstallerPackageName = null;
5155 synchronized (mPackages) {
5156 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
5157 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005158
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005159 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005161 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 res.removedInfo)) {
5163 // If the existing package was'nt successfully deleted
5164 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5165 deletedPkg = false;
5166 } else {
5167 // Successfully deleted the old package. Now proceed with re-installation
5168 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005169 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005170 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005171 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5173 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005174 }
5175 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005176 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005177 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 res);
5179 updatedSettings = true;
5180 }
5181 }
5182
5183 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5184 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005185 // were keeping around in case we needed them (see below) can now be deleted.
5186 // This info will be set on the res.removedInfo to clean up later on as post
5187 // install action.
5188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 //update signature on the new package setting
5190 //this should always succeed, since we checked the
5191 //signature earlier.
5192 synchronized(mPackages) {
5193 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
5194 parseFlags, true);
5195 }
5196 } else {
5197 // remove package from internal structures. Note that we want deletePackageX to
5198 // delete the package data and cache directories that it created in
5199 // scanPackageLocked, unless those directories existed before we even tried to
5200 // install.
5201 if(updatedSettings) {
5202 deletePackageLI(
5203 pkgName, true,
5204 PackageManager.DONT_DELETE_DATA,
5205 res.removedInfo);
5206 }
5207 // Since we failed to install the new package we need to restore the old
5208 // package that we deleted.
5209 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005210 File restoreFile = new File(deletedPackage.mPath);
5211 if (restoreFile == null) {
5212 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
5213 return;
5214 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005215 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
5216 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005217 // Parse old package
5218 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
5219 scanPackageLI(restoreFile, parseFlags, scanMode);
5220 synchronized (mPackages) {
5221 grantPermissionsLP(deletedPackage, false);
5222 mSettings.writeLP();
5223 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005224 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5225 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
5226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005227 }
5228 }
5229 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005232 PackageParser.Package pkg,
5233 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005234 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 PackageParser.Package newPackage = null;
5236 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005237 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005238 PackageParser.PARSE_IS_SYSTEM;
5239 String packageName = deletedPackage.packageName;
5240 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5241 if (packageName == null) {
5242 Log.w(TAG, "Attempt to delete null packageName.");
5243 return;
5244 }
5245 PackageParser.Package oldPkg;
5246 PackageSetting oldPkgSetting;
5247 synchronized (mPackages) {
5248 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005249 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5251 (oldPkgSetting == null)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005252 Log.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 return;
5254 }
5255 }
5256 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5257 res.removedInfo.removedPackage = packageName;
5258 // Remove existing system package
5259 removePackageLI(oldPkg, true);
5260 synchronized (mPackages) {
5261 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
5262 }
5263
5264 // Successfully disabled the old package. Now proceed with re-installation
5265 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5266 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005267 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005268 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005269 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5271 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5272 }
5273 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005274 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005275 updatedSettings = true;
5276 }
5277
5278 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5279 //update signature on the new package setting
5280 //this should always succeed, since we checked the
5281 //signature earlier.
5282 synchronized(mPackages) {
5283 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
5284 parseFlags, true);
5285 }
5286 } else {
5287 // Re installation failed. Restore old information
5288 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005289 if (newPackage != null) {
5290 removePackageLI(newPackage, true);
5291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005293 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07005295 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 // Restore the old system information in Settings
5297 synchronized(mPackages) {
5298 if(updatedSettings) {
5299 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005300 mSettings.setInstallerPackageName(packageName,
5301 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005302 }
5303 mSettings.writeLP();
5304 }
5305 }
5306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005307
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005308 // Utility method used to move dex files during install.
5309 private int moveDexFiles(PackageParser.Package newPackage) {
5310 int retCode;
5311 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5312 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5313 if (retCode != 0) {
5314 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
5315 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5316 }
5317 }
5318 return PackageManager.INSTALL_SUCCEEDED;
5319 }
5320
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005321 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005322 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005323 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005324 synchronized (mPackages) {
5325 //write settings. the installStatus will be incomplete at this stage.
5326 //note that the new package setting would have already been
5327 //added to mPackages. It hasn't been persisted yet.
5328 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5329 mSettings.writeLP();
5330 }
5331
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005332 if ((res.returnCode = moveDexFiles(newPackage))
5333 != PackageManager.INSTALL_SUCCEEDED) {
5334 // Discontinue if moving dex files failed.
5335 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005336 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005337 if((res.returnCode = setPermissionsLI(newPackage))
5338 != PackageManager.INSTALL_SUCCEEDED) {
5339 if (mInstaller != null) {
5340 mInstaller.rmdex(newPackage.mScanPath);
5341 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005342 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005344 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 synchronized (mPackages) {
5347 grantPermissionsLP(newPackage, true);
5348 res.name = pkgName;
5349 res.uid = newPackage.applicationInfo.uid;
5350 res.pkg = newPackage;
5351 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005352 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5354 //to update install status
5355 mSettings.writeLP();
5356 }
5357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005358
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005359 private void installPackageLI(InstallArgs args,
5360 boolean newInstall, PackageInstalledInfo res) {
5361 int pFlags = args.flags;
5362 String installerPackageName = args.installerPackageName;
5363 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005364 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005365 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005366 boolean replace = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005367 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
5368 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005369 // Result object to be returned
5370 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5371
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005372 // Retrieve PackageSettings and parse package
5373 int parseFlags = PackageParser.PARSE_CHATTY |
5374 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5375 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5376 parseFlags |= mDefParseFlags;
5377 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5378 pp.setSeparateProcesses(mSeparateProcesses);
5379 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5380 null, mMetrics, parseFlags);
5381 if (pkg == null) {
5382 res.returnCode = pp.getParseError();
5383 return;
5384 }
5385 String pkgName = res.name = pkg.packageName;
5386 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5387 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5388 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5389 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005391 }
5392 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5393 res.returnCode = pp.getParseError();
5394 return;
5395 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005396 // Get rid of all references to package scan path via parser.
5397 pp = null;
5398 String oldCodePath = null;
5399 boolean systemApp = false;
5400 synchronized (mPackages) {
5401 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005402 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5403 String oldName = mSettings.mRenamedPackages.get(pkgName);
5404 if (oldName != null && oldName.equals(pkg.mOriginalPackage)
5405 && mPackages.containsKey(oldName)) {
5406 // This package is derived from an original package,
5407 // and this device has been updating from that original
5408 // name. We must continue using the original name, so
5409 // rename the new package here.
5410 pkg.setPackageName(pkg.mOriginalPackage);
5411 pkgName = pkg.packageName;
5412 replace = true;
5413 } else if (mPackages.containsKey(pkgName)) {
5414 // This package, under its official name, already exists
5415 // on the device; we should replace it.
5416 replace = true;
5417 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005418 }
5419 PackageSetting ps = mSettings.mPackages.get(pkgName);
5420 if (ps != null) {
5421 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5422 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5423 systemApp = (ps.pkg.applicationInfo.flags &
5424 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005425 }
5426 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005427 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005428
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005429 if (systemApp && onSd) {
5430 // Disable updates to system apps on sdcard
5431 Log.w(TAG, "Cannot install updates to system apps on sdcard");
5432 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5433 return;
5434 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08005435
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005436 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5437 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5438 return;
5439 }
5440 // Set application objects path explicitly after the rename
5441 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005442 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005443 replacePackageLI(pkg, parseFlags, scanMode,
5444 installerPackageName, res);
5445 } else {
5446 installNewPackageLI(pkg, parseFlags, scanMode,
5447 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005448 }
5449 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005450
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005451 private int setPermissionsLI(PackageParser.Package newPackage) {
5452 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005453 int retCode = 0;
5454 // TODO Gross hack but fix later. Ideally move this to be a post installation
5455 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005456 if ((newPackage.applicationInfo.flags
5457 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
5458 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 try {
5460 extractPublicFiles(newPackage, destResourceFile);
5461 } catch (IOException e) {
5462 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
5463 " forward-locked app.");
5464 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5465 } finally {
5466 //TODO clean up the extracted public files
5467 }
5468 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005469 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 newPackage.applicationInfo.uid);
5471 } else {
5472 final int filePermissions =
5473 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005474 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 newPackage.applicationInfo.uid);
5476 }
5477 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005478 // The permissions on the resource file was set when it was copied for
5479 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005483 Log.e(TAG, "Couldn't set new package file permissions for " +
5484 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005485 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005486 // TODO Define new internal error
5487 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 }
5489 return PackageManager.INSTALL_SUCCEEDED;
5490 }
5491
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005492 private boolean isForwardLocked(PackageParser.Package pkg) {
5493 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 }
5495
5496 private void extractPublicFiles(PackageParser.Package newPackage,
5497 File publicZipFile) throws IOException {
5498 final ZipOutputStream publicZipOutStream =
5499 new ZipOutputStream(new FileOutputStream(publicZipFile));
5500 final ZipFile privateZip = new ZipFile(newPackage.mPath);
5501
5502 // Copy manifest, resources.arsc and res directory to public zip
5503
5504 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
5505 while (privateZipEntries.hasMoreElements()) {
5506 final ZipEntry zipEntry = privateZipEntries.nextElement();
5507 final String zipEntryName = zipEntry.getName();
5508 if ("AndroidManifest.xml".equals(zipEntryName)
5509 || "resources.arsc".equals(zipEntryName)
5510 || zipEntryName.startsWith("res/")) {
5511 try {
5512 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
5513 } catch (IOException e) {
5514 try {
5515 publicZipOutStream.close();
5516 throw e;
5517 } finally {
5518 publicZipFile.delete();
5519 }
5520 }
5521 }
5522 }
5523
5524 publicZipOutStream.close();
5525 FileUtils.setPermissions(
5526 publicZipFile.getAbsolutePath(),
5527 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
5528 -1, -1);
5529 }
5530
5531 private static void copyZipEntry(ZipEntry zipEntry,
5532 ZipFile inZipFile,
5533 ZipOutputStream outZipStream) throws IOException {
5534 byte[] buffer = new byte[4096];
5535 int num;
5536
5537 ZipEntry newEntry;
5538 if (zipEntry.getMethod() == ZipEntry.STORED) {
5539 // Preserve the STORED method of the input entry.
5540 newEntry = new ZipEntry(zipEntry);
5541 } else {
5542 // Create a new entry so that the compressed len is recomputed.
5543 newEntry = new ZipEntry(zipEntry.getName());
5544 }
5545 outZipStream.putNextEntry(newEntry);
5546
5547 InputStream data = inZipFile.getInputStream(zipEntry);
5548 while ((num = data.read(buffer)) > 0) {
5549 outZipStream.write(buffer, 0, num);
5550 }
5551 outZipStream.flush();
5552 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005554 private void deleteTempPackageFiles() {
5555 FilenameFilter filter = new FilenameFilter() {
5556 public boolean accept(File dir, String name) {
5557 return name.startsWith("vmdl") && name.endsWith(".tmp");
5558 }
5559 };
5560 String tmpFilesList[] = mAppInstallDir.list(filter);
5561 if(tmpFilesList == null) {
5562 return;
5563 }
5564 for(int i = 0; i < tmpFilesList.length; i++) {
5565 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
5566 tmpFile.delete();
5567 }
5568 }
5569
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005570 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 File tmpPackageFile;
5572 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005573 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 } catch (IOException e) {
5575 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
5576 return null;
5577 }
5578 try {
5579 FileUtils.setPermissions(
5580 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
5581 -1, -1);
5582 } catch (IOException e) {
5583 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
5584 return null;
5585 }
5586 return tmpPackageFile;
5587 }
5588
5589 public void deletePackage(final String packageName,
5590 final IPackageDeleteObserver observer,
5591 final int flags) {
5592 mContext.enforceCallingOrSelfPermission(
5593 android.Manifest.permission.DELETE_PACKAGES, null);
5594 // Queue up an async operation since the package deletion may take a little while.
5595 mHandler.post(new Runnable() {
5596 public void run() {
5597 mHandler.removeCallbacks(this);
5598 final boolean succeded = deletePackageX(packageName, true, true, flags);
5599 if (observer != null) {
5600 try {
5601 observer.packageDeleted(succeded);
5602 } catch (RemoteException e) {
5603 Log.i(TAG, "Observer no longer exists.");
5604 } //end catch
5605 } //end if
5606 } //end run
5607 });
5608 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005610 /**
5611 * This method is an internal method that could be get invoked either
5612 * to delete an installed package or to clean up a failed installation.
5613 * After deleting an installed package, a broadcast is sent to notify any
5614 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005615 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 * installation wouldn't have sent the initial broadcast either
5617 * The key steps in deleting a package are
5618 * deleting the package information in internal structures like mPackages,
5619 * deleting the packages base directories through installd
5620 * updating mSettings to reflect current status
5621 * persisting settings for later use
5622 * sending a broadcast if necessary
5623 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 private boolean deletePackageX(String packageName, boolean sendBroadCast,
5625 boolean deleteCodeAndResources, int flags) {
5626 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07005627 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005629 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
5630 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
5631 try {
5632 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
5633 Log.w(TAG, "Not removing package " + packageName + ": has active device admin");
5634 return false;
5635 }
5636 } catch (RemoteException e) {
5637 }
5638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 synchronized (mInstallLock) {
5640 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
5641 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07005644 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
5645 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
5646
5647 // If the removed package was a system update, the old system packaged
5648 // was re-enabled; we need to broadcast this information
5649 if (systemUpdate) {
5650 Bundle extras = new Bundle(1);
5651 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
5652 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5653
5654 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
5655 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
5656 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005657 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005658 // Delete the resources here after sending the broadcast to let
5659 // other processes clean up before deleting resources.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005660 if (info.args != null) {
5661 synchronized (mInstallLock) {
5662 info.args.doPostDeleteLI(deleteCodeAndResources);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005663 }
5664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 return res;
5666 }
5667
5668 static class PackageRemovedInfo {
5669 String removedPackage;
5670 int uid = -1;
5671 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07005672 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005673 // Clean up resources deleted packages.
5674 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07005675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 void sendBroadcast(boolean fullRemove, boolean replacing) {
5677 Bundle extras = new Bundle(1);
5678 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
5679 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
5680 if (replacing) {
5681 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5682 }
5683 if (removedPackage != null) {
5684 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
5685 }
5686 if (removedUid >= 0) {
5687 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5688 }
5689 }
5690 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 /*
5693 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5694 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005695 * 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 -08005696 * delete a partially installed application.
5697 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005698 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 int flags) {
5700 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005701 if (outInfo != null) {
5702 outInfo.removedPackage = packageName;
5703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005704 removePackageLI(p, true);
5705 // Retrieve object to delete permissions for shared user later on
5706 PackageSetting deletedPs;
5707 synchronized (mPackages) {
5708 deletedPs = mSettings.mPackages.get(packageName);
5709 }
5710 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005711 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005713 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 if (retCode < 0) {
5715 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5716 + packageName + ", retcode=" + retCode);
5717 // we don't consider this to be a failure of the core package deletion
5718 }
5719 } else {
5720 //for emulator
5721 PackageParser.Package pkg = mPackages.get(packageName);
5722 File dataDir = new File(pkg.applicationInfo.dataDir);
5723 dataDir.delete();
5724 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005725 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005727 if (outInfo != null) {
5728 outInfo.removedUid = mSettings.removePackageLP(packageName);
5729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 }
5731 }
5732 synchronized (mPackages) {
5733 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5734 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005735 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005737 if (deletedPs != null) {
5738 // remove from preferred activities.
5739 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
5740 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
5741 if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
5742 removed.add(pa);
5743 }
5744 }
5745 for (PreferredActivity pa : removed) {
5746 mSettings.mPreferredActivities.removeFilter(pa);
5747 }
5748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005749 // Save settings now
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005750 mSettings.writeLP();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 }
5752 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 /*
5755 * Tries to delete system package.
5756 */
5757 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005758 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005759 ApplicationInfo applicationInfo = p.applicationInfo;
5760 //applicable for non-partially installed applications only
5761 if (applicationInfo == null) {
5762 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5763 return false;
5764 }
5765 PackageSetting ps = null;
5766 // Confirm if the system package has been updated
5767 // An updated system app can be deleted. This will also have to restore
5768 // the system pkg from system partition
5769 synchronized (mPackages) {
5770 ps = mSettings.getDisabledSystemPkg(p.packageName);
5771 }
5772 if (ps == null) {
5773 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5774 return false;
5775 } else {
5776 Log.i(TAG, "Deleting system pkg from data partition");
5777 }
5778 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005779 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005780 boolean deleteCodeAndResources = false;
5781 if (ps.versionCode < p.mVersionCode) {
5782 // Delete code and resources for downgrades
5783 deleteCodeAndResources = true;
5784 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5785 flags &= ~PackageManager.DONT_DELETE_DATA;
5786 }
5787 } else {
5788 // Preserve data by setting flag
5789 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5790 flags |= PackageManager.DONT_DELETE_DATA;
5791 }
5792 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005793 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5794 if (!ret) {
5795 return false;
5796 }
5797 synchronized (mPackages) {
5798 // Reinstate the old system package
5799 mSettings.enableSystemPackageLP(p.packageName);
5800 }
5801 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005802 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005804 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 if (newPkg == null) {
5807 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5808 return false;
5809 }
5810 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005811 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005812 mSettings.writeLP();
5813 }
5814 return true;
5815 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5818 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5819 ApplicationInfo applicationInfo = p.applicationInfo;
5820 if (applicationInfo == null) {
5821 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5822 return false;
5823 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005824 if (outInfo != null) {
5825 outInfo.uid = applicationInfo.uid;
5826 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827
5828 // Delete package data from internal structures and also remove data if flag is set
5829 removePackageDataLI(p, outInfo, flags);
5830
5831 // Delete application code and resources
5832 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005833 // TODO can pick up from PackageSettings as well
5834 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005835 PackageManager.INSTALL_EXTERNAL : 0;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005836 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5837 PackageManager.INSTALL_FORWARD_LOCK : 0;
5838 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005839 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 }
5841 return true;
5842 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 /*
5845 * This method handles package deletion in general
5846 */
5847 private boolean deletePackageLI(String packageName,
5848 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5849 if (packageName == null) {
5850 Log.w(TAG, "Attempt to delete null packageName.");
5851 return false;
5852 }
5853 PackageParser.Package p;
5854 boolean dataOnly = false;
5855 synchronized (mPackages) {
5856 p = mPackages.get(packageName);
5857 if (p == null) {
5858 //this retrieves partially installed apps
5859 dataOnly = true;
5860 PackageSetting ps = mSettings.mPackages.get(packageName);
5861 if (ps == null) {
5862 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5863 return false;
5864 }
5865 p = ps.pkg;
5866 }
5867 }
5868 if (p == null) {
5869 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5870 return false;
5871 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 if (dataOnly) {
5874 // Delete application data first
5875 removePackageDataLI(p, outInfo, flags);
5876 return true;
5877 }
5878 // At this point the package should have ApplicationInfo associated with it
5879 if (p.applicationInfo == null) {
5880 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5881 return false;
5882 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005883 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5885 Log.i(TAG, "Removing system package:"+p.packageName);
5886 // When an updated system application is deleted we delete the existing resources as well and
5887 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005888 ret = deleteSystemPackageLI(p, flags, outInfo);
5889 } else {
5890 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005891 // Kill application pre-emptively especially for apps on sd.
5892 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005893 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005895 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 public void clearApplicationUserData(final String packageName,
5899 final IPackageDataObserver observer) {
5900 mContext.enforceCallingOrSelfPermission(
5901 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
5902 // Queue up an async operation since the package deletion may take a little while.
5903 mHandler.post(new Runnable() {
5904 public void run() {
5905 mHandler.removeCallbacks(this);
5906 final boolean succeeded;
5907 synchronized (mInstallLock) {
5908 succeeded = clearApplicationUserDataLI(packageName);
5909 }
5910 if (succeeded) {
5911 // invoke DeviceStorageMonitor's update method to clear any notifications
5912 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
5913 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
5914 if (dsm != null) {
5915 dsm.updateMemory();
5916 }
5917 }
5918 if(observer != null) {
5919 try {
5920 observer.onRemoveCompleted(packageName, succeeded);
5921 } catch (RemoteException e) {
5922 Log.i(TAG, "Observer no longer exists.");
5923 }
5924 } //end if observer
5925 } //end run
5926 });
5927 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005929 private boolean clearApplicationUserDataLI(String packageName) {
5930 if (packageName == null) {
5931 Log.w(TAG, "Attempt to delete null packageName.");
5932 return false;
5933 }
5934 PackageParser.Package p;
5935 boolean dataOnly = false;
5936 synchronized (mPackages) {
5937 p = mPackages.get(packageName);
5938 if(p == null) {
5939 dataOnly = true;
5940 PackageSetting ps = mSettings.mPackages.get(packageName);
5941 if((ps == null) || (ps.pkg == null)) {
5942 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5943 return false;
5944 }
5945 p = ps.pkg;
5946 }
5947 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005948 boolean useEncryptedFSDir = false;
5949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 if(!dataOnly) {
5951 //need to check this only for fully installed applications
5952 if (p == null) {
5953 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5954 return false;
5955 }
5956 final ApplicationInfo applicationInfo = p.applicationInfo;
5957 if (applicationInfo == null) {
5958 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5959 return false;
5960 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005961 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005964 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 if (retCode < 0) {
5966 Log.w(TAG, "Couldn't remove cache files for package: "
5967 + packageName);
5968 return false;
5969 }
5970 }
5971 return true;
5972 }
5973
5974 public void deleteApplicationCacheFiles(final String packageName,
5975 final IPackageDataObserver observer) {
5976 mContext.enforceCallingOrSelfPermission(
5977 android.Manifest.permission.DELETE_CACHE_FILES, null);
5978 // Queue up an async operation since the package deletion may take a little while.
5979 mHandler.post(new Runnable() {
5980 public void run() {
5981 mHandler.removeCallbacks(this);
5982 final boolean succeded;
5983 synchronized (mInstallLock) {
5984 succeded = deleteApplicationCacheFilesLI(packageName);
5985 }
5986 if(observer != null) {
5987 try {
5988 observer.onRemoveCompleted(packageName, succeded);
5989 } catch (RemoteException e) {
5990 Log.i(TAG, "Observer no longer exists.");
5991 }
5992 } //end if observer
5993 } //end run
5994 });
5995 }
5996
5997 private boolean deleteApplicationCacheFilesLI(String packageName) {
5998 if (packageName == null) {
5999 Log.w(TAG, "Attempt to delete null packageName.");
6000 return false;
6001 }
6002 PackageParser.Package p;
6003 synchronized (mPackages) {
6004 p = mPackages.get(packageName);
6005 }
6006 if (p == null) {
6007 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6008 return false;
6009 }
6010 final ApplicationInfo applicationInfo = p.applicationInfo;
6011 if (applicationInfo == null) {
6012 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
6013 return false;
6014 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006015 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006017 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 if (retCode < 0) {
6019 Log.w(TAG, "Couldn't remove cache files for package: "
6020 + packageName);
6021 return false;
6022 }
6023 }
6024 return true;
6025 }
6026
6027 public void getPackageSizeInfo(final String packageName,
6028 final IPackageStatsObserver observer) {
6029 mContext.enforceCallingOrSelfPermission(
6030 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6031 // Queue up an async operation since the package deletion may take a little while.
6032 mHandler.post(new Runnable() {
6033 public void run() {
6034 mHandler.removeCallbacks(this);
6035 PackageStats lStats = new PackageStats(packageName);
6036 final boolean succeded;
6037 synchronized (mInstallLock) {
6038 succeded = getPackageSizeInfoLI(packageName, lStats);
6039 }
6040 if(observer != null) {
6041 try {
6042 observer.onGetStatsCompleted(lStats, succeded);
6043 } catch (RemoteException e) {
6044 Log.i(TAG, "Observer no longer exists.");
6045 }
6046 } //end if observer
6047 } //end run
6048 });
6049 }
6050
6051 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6052 if (packageName == null) {
6053 Log.w(TAG, "Attempt to get size of null packageName.");
6054 return false;
6055 }
6056 PackageParser.Package p;
6057 boolean dataOnly = false;
6058 synchronized (mPackages) {
6059 p = mPackages.get(packageName);
6060 if(p == null) {
6061 dataOnly = true;
6062 PackageSetting ps = mSettings.mPackages.get(packageName);
6063 if((ps == null) || (ps.pkg == null)) {
6064 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6065 return false;
6066 }
6067 p = ps.pkg;
6068 }
6069 }
6070 String publicSrcDir = null;
6071 if(!dataOnly) {
6072 final ApplicationInfo applicationInfo = p.applicationInfo;
6073 if (applicationInfo == null) {
6074 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
6075 return false;
6076 }
6077 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6078 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006079 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 if (mInstaller != null) {
6081 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08006082 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006083 if (res < 0) {
6084 return false;
6085 } else {
6086 return true;
6087 }
6088 }
6089 return true;
6090 }
6091
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 public void addPackageToPreferred(String packageName) {
6094 mContext.enforceCallingOrSelfPermission(
6095 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006096 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 }
6098
6099 public void removePackageFromPreferred(String packageName) {
6100 mContext.enforceCallingOrSelfPermission(
6101 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006102 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 }
6104
6105 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006106 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 }
6108
6109 public void addPreferredActivity(IntentFilter filter, int match,
6110 ComponentName[] set, ComponentName activity) {
6111 mContext.enforceCallingOrSelfPermission(
6112 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6113
6114 synchronized (mPackages) {
6115 Log.i(TAG, "Adding preferred activity " + activity + ":");
6116 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6117 mSettings.mPreferredActivities.addFilter(
6118 new PreferredActivity(filter, match, set, activity));
6119 mSettings.writeLP();
6120 }
6121 }
6122
Satish Sampath8dbe6122009-06-02 23:35:54 +01006123 public void replacePreferredActivity(IntentFilter filter, int match,
6124 ComponentName[] set, ComponentName activity) {
6125 mContext.enforceCallingOrSelfPermission(
6126 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6127 if (filter.countActions() != 1) {
6128 throw new IllegalArgumentException(
6129 "replacePreferredActivity expects filter to have only 1 action.");
6130 }
6131 if (filter.countCategories() != 1) {
6132 throw new IllegalArgumentException(
6133 "replacePreferredActivity expects filter to have only 1 category.");
6134 }
6135 if (filter.countDataAuthorities() != 0
6136 || filter.countDataPaths() != 0
6137 || filter.countDataSchemes() != 0
6138 || filter.countDataTypes() != 0) {
6139 throw new IllegalArgumentException(
6140 "replacePreferredActivity expects filter to have no data authorities, " +
6141 "paths, schemes or types.");
6142 }
6143 synchronized (mPackages) {
6144 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6145 String action = filter.getAction(0);
6146 String category = filter.getCategory(0);
6147 while (it.hasNext()) {
6148 PreferredActivity pa = it.next();
6149 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6150 it.remove();
6151 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
6152 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6153 }
6154 }
6155 addPreferredActivity(filter, match, set, activity);
6156 }
6157 }
6158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 public void clearPackagePreferredActivities(String packageName) {
6160 mContext.enforceCallingOrSelfPermission(
6161 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6162
6163 synchronized (mPackages) {
6164 if (clearPackagePreferredActivitiesLP(packageName)) {
6165 mSettings.writeLP();
6166 }
6167 }
6168 }
6169
6170 boolean clearPackagePreferredActivitiesLP(String packageName) {
6171 boolean changed = false;
6172 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6173 while (it.hasNext()) {
6174 PreferredActivity pa = it.next();
6175 if (pa.mActivity.getPackageName().equals(packageName)) {
6176 it.remove();
6177 changed = true;
6178 }
6179 }
6180 return changed;
6181 }
6182
6183 public int getPreferredActivities(List<IntentFilter> outFilters,
6184 List<ComponentName> outActivities, String packageName) {
6185
6186 int num = 0;
6187 synchronized (mPackages) {
6188 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6189 while (it.hasNext()) {
6190 PreferredActivity pa = it.next();
6191 if (packageName == null
6192 || pa.mActivity.getPackageName().equals(packageName)) {
6193 if (outFilters != null) {
6194 outFilters.add(new IntentFilter(pa));
6195 }
6196 if (outActivities != null) {
6197 outActivities.add(pa.mActivity);
6198 }
6199 }
6200 }
6201 }
6202
6203 return num;
6204 }
6205
6206 public void setApplicationEnabledSetting(String appPackageName,
6207 int newState, int flags) {
6208 setEnabledSetting(appPackageName, null, newState, flags);
6209 }
6210
6211 public void setComponentEnabledSetting(ComponentName componentName,
6212 int newState, int flags) {
6213 setEnabledSetting(componentName.getPackageName(),
6214 componentName.getClassName(), newState, flags);
6215 }
6216
6217 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006218 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
6220 || newState == COMPONENT_ENABLED_STATE_ENABLED
6221 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
6222 throw new IllegalArgumentException("Invalid new component state: "
6223 + newState);
6224 }
6225 PackageSetting pkgSetting;
6226 final int uid = Binder.getCallingUid();
6227 final int permission = mContext.checkCallingPermission(
6228 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
6229 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006230 boolean sendNow = false;
6231 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006232 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006234 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006235 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006236 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006238 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006239 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006240 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006241 }
6242 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006243 "Unknown component: " + packageName
6244 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006245 }
6246 if (!allowedByPermission && (uid != pkgSetting.userId)) {
6247 throw new SecurityException(
6248 "Permission Denial: attempt to change component state from pid="
6249 + Binder.getCallingPid()
6250 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
6251 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006252 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006253 // We're dealing with an application/package level state change
6254 pkgSetting.enabled = newState;
6255 } else {
6256 // We're dealing with a component level state change
6257 switch (newState) {
6258 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006259 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 break;
6261 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006262 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 break;
6264 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006265 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 break;
6267 default:
6268 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006269 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 }
6271 }
6272 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006273 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006274 components = mPendingBroadcasts.get(packageName);
6275 boolean newPackage = components == null;
6276 if (newPackage) {
6277 components = new ArrayList<String>();
6278 }
6279 if (!components.contains(componentName)) {
6280 components.add(componentName);
6281 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006282 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6283 sendNow = true;
6284 // Purge entry from pending broadcast list if another one exists already
6285 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006286 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006287 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006288 if (newPackage) {
6289 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006290 }
6291 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6292 // Schedule a message
6293 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6294 }
6295 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 long callingId = Binder.clearCallingIdentity();
6299 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006300 if (sendNow) {
6301 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006302 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 } finally {
6305 Binder.restoreCallingIdentity(callingId);
6306 }
6307 }
6308
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006309 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006310 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6311 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6312 + " components=" + componentNames);
6313 Bundle extras = new Bundle(4);
6314 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6315 String nameList[] = new String[componentNames.size()];
6316 componentNames.toArray(nameList);
6317 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006318 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
6319 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006320 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006321 }
6322
Jacek Surazski65e13172009-04-28 15:26:38 +02006323 public String getInstallerPackageName(String packageName) {
6324 synchronized (mPackages) {
6325 PackageSetting pkg = mSettings.mPackages.get(packageName);
6326 if (pkg == null) {
6327 throw new IllegalArgumentException("Unknown package: " + packageName);
6328 }
6329 return pkg.installerPackageName;
6330 }
6331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006333 public int getApplicationEnabledSetting(String appPackageName) {
6334 synchronized (mPackages) {
6335 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
6336 if (pkg == null) {
6337 throw new IllegalArgumentException("Unknown package: " + appPackageName);
6338 }
6339 return pkg.enabled;
6340 }
6341 }
6342
6343 public int getComponentEnabledSetting(ComponentName componentName) {
6344 synchronized (mPackages) {
6345 final String packageNameStr = componentName.getPackageName();
6346 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
6347 if (pkg == null) {
6348 throw new IllegalArgumentException("Unknown component: " + componentName);
6349 }
6350 final String classNameStr = componentName.getClassName();
6351 return pkg.currentEnabledStateLP(classNameStr);
6352 }
6353 }
6354
6355 public void enterSafeMode() {
6356 if (!mSystemReady) {
6357 mSafeMode = true;
6358 }
6359 }
6360
6361 public void systemReady() {
6362 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006363
6364 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006365 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006366 mContext.getContentResolver(),
6367 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006368 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006369 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006370 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 }
6373
6374 public boolean isSafeMode() {
6375 return mSafeMode;
6376 }
6377
6378 public boolean hasSystemUidErrors() {
6379 return mHasSystemUidErrors;
6380 }
6381
6382 static String arrayToString(int[] array) {
6383 StringBuffer buf = new StringBuffer(128);
6384 buf.append('[');
6385 if (array != null) {
6386 for (int i=0; i<array.length; i++) {
6387 if (i > 0) buf.append(", ");
6388 buf.append(array[i]);
6389 }
6390 }
6391 buf.append(']');
6392 return buf.toString();
6393 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006395 @Override
6396 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6397 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6398 != PackageManager.PERMISSION_GRANTED) {
6399 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6400 + Binder.getCallingPid()
6401 + ", uid=" + Binder.getCallingUid()
6402 + " without permission "
6403 + android.Manifest.permission.DUMP);
6404 return;
6405 }
6406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 synchronized (mPackages) {
6408 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006409 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 pw.println(" ");
6411 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006412 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 pw.println(" ");
6414 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006415 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006416 pw.println(" ");
6417 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006418 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006419 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 pw.println("Permissions:");
6421 {
6422 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006423 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
6424 pw.print(Integer.toHexString(System.identityHashCode(p)));
6425 pw.println("):");
6426 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
6427 pw.print(" uid="); pw.print(p.uid);
6428 pw.print(" gids="); pw.print(arrayToString(p.gids));
6429 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 }
6431 }
6432 pw.println(" ");
6433 pw.println("Packages:");
6434 {
6435 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006436 pw.print(" Package [");
6437 pw.print(ps.realName != null ? ps.realName : ps.name);
6438 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006439 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6440 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006441 if (ps.realName != null) {
6442 pw.print(" compat name="); pw.println(ps.name);
6443 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006444 pw.print(" userId="); pw.print(ps.userId);
6445 pw.print(" gids="); pw.println(arrayToString(ps.gids));
6446 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6447 pw.print(" pkg="); pw.println(ps.pkg);
6448 pw.print(" codePath="); pw.println(ps.codePathString);
6449 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006450 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006451 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006452 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006453 pw.print(" supportsScreens=[");
6454 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006455 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006456 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006457 if (!first) pw.print(", ");
6458 first = false;
6459 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006460 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006461 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006462 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006463 if (!first) pw.print(", ");
6464 first = false;
6465 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006467 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006468 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006469 if (!first) pw.print(", ");
6470 first = false;
6471 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006472 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006473 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006474 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006475 if (!first) pw.print(", ");
6476 first = false;
6477 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006478 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006479 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006480 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
6481 if (!first) pw.print(", ");
6482 first = false;
6483 pw.print("anyDensity");
6484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006486 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006487 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
6488 pw.print(" signatures="); pw.println(ps.signatures);
6489 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
6490 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
6491 pw.print(" installStatus="); pw.print(ps.installStatus);
6492 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 if (ps.disabledComponents.size() > 0) {
6494 pw.println(" disabledComponents:");
6495 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006496 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 }
6498 }
6499 if (ps.enabledComponents.size() > 0) {
6500 pw.println(" enabledComponents:");
6501 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006502 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 }
6504 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006505 if (ps.grantedPermissions.size() > 0) {
6506 pw.println(" grantedPermissions:");
6507 for (String s : ps.grantedPermissions) {
6508 pw.print(" "); pw.println(s);
6509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006511 if (ps.loadedPermissions.size() > 0) {
6512 pw.println(" loadedPermissions:");
6513 for (String s : ps.loadedPermissions) {
6514 pw.print(" "); pw.println(s);
6515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 }
6517 }
6518 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006519 if (mSettings.mRenamedPackages.size() > 0) {
6520 pw.println(" ");
6521 pw.println("Renamed packages:");
6522 for (HashMap.Entry<String, String> e
6523 : mSettings.mRenamedPackages.entrySet()) {
6524 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
6525 pw.println(e.getValue());
6526 }
6527 }
6528 if (mSettings.mDisabledSysPackages.size() > 0) {
6529 pw.println(" ");
6530 pw.println("Hidden system packages:");
6531 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
6532 pw.print(" Package [");
6533 pw.print(ps.realName != null ? ps.realName : ps.name);
6534 pw.print("] (");
6535 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6536 pw.println("):");
6537 if (ps.realName != null) {
6538 pw.print(" compat name="); pw.println(ps.name);
6539 }
6540 pw.print(" userId="); pw.println(ps.userId);
6541 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6542 pw.print(" codePath="); pw.println(ps.codePathString);
6543 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
6544 }
6545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 pw.println(" ");
6547 pw.println("Shared Users:");
6548 {
6549 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006550 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
6551 pw.print(Integer.toHexString(System.identityHashCode(su)));
6552 pw.println("):");
6553 pw.print(" userId="); pw.print(su.userId);
6554 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006555 pw.println(" grantedPermissions:");
6556 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006557 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006558 }
6559 pw.println(" loadedPermissions:");
6560 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006561 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 }
6563 }
6564 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 pw.println(" ");
6567 pw.println("Settings parse messages:");
6568 pw.println(mSettings.mReadMessages.toString());
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006569
6570 pw.println(" ");
6571 pw.println("Package warning messages:");
6572 File fname = getSettingsProblemFile();
6573 FileInputStream in;
6574 try {
6575 in = new FileInputStream(fname);
6576 int avail = in.available();
6577 byte[] data = new byte[avail];
6578 in.read(data);
6579 pw.println(new String(data));
6580 } catch (FileNotFoundException e) {
6581 } catch (IOException e) {
6582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006583 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006584
6585 synchronized (mProviders) {
6586 pw.println(" ");
6587 pw.println("Registered ContentProviders:");
6588 for (PackageParser.Provider p : mProviders.values()) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006589 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006590 pw.println(p.toString());
6591 }
6592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 }
6594
6595 static final class BasePermission {
6596 final static int TYPE_NORMAL = 0;
6597 final static int TYPE_BUILTIN = 1;
6598 final static int TYPE_DYNAMIC = 2;
6599
6600 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006601 String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 final int type;
6603 PackageParser.Permission perm;
6604 PermissionInfo pendingInfo;
6605 int uid;
6606 int[] gids;
6607
6608 BasePermission(String _name, String _sourcePackage, int _type) {
6609 name = _name;
6610 sourcePackage = _sourcePackage;
6611 type = _type;
6612 }
6613 }
6614
6615 static class PackageSignatures {
6616 private Signature[] mSignatures;
6617
6618 PackageSignatures(Signature[] sigs) {
6619 assignSignatures(sigs);
6620 }
6621
6622 PackageSignatures() {
6623 }
6624
6625 void writeXml(XmlSerializer serializer, String tagName,
6626 ArrayList<Signature> pastSignatures) throws IOException {
6627 if (mSignatures == null) {
6628 return;
6629 }
6630 serializer.startTag(null, tagName);
6631 serializer.attribute(null, "count",
6632 Integer.toString(mSignatures.length));
6633 for (int i=0; i<mSignatures.length; i++) {
6634 serializer.startTag(null, "cert");
6635 final Signature sig = mSignatures[i];
6636 final int sigHash = sig.hashCode();
6637 final int numPast = pastSignatures.size();
6638 int j;
6639 for (j=0; j<numPast; j++) {
6640 Signature pastSig = pastSignatures.get(j);
6641 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
6642 serializer.attribute(null, "index", Integer.toString(j));
6643 break;
6644 }
6645 }
6646 if (j >= numPast) {
6647 pastSignatures.add(sig);
6648 serializer.attribute(null, "index", Integer.toString(numPast));
6649 serializer.attribute(null, "key", sig.toCharsString());
6650 }
6651 serializer.endTag(null, "cert");
6652 }
6653 serializer.endTag(null, tagName);
6654 }
6655
6656 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
6657 throws IOException, XmlPullParserException {
6658 String countStr = parser.getAttributeValue(null, "count");
6659 if (countStr == null) {
6660 reportSettingsProblem(Log.WARN,
6661 "Error in package manager settings: <signatures> has"
6662 + " no count at " + parser.getPositionDescription());
6663 XmlUtils.skipCurrentTag(parser);
6664 }
6665 final int count = Integer.parseInt(countStr);
6666 mSignatures = new Signature[count];
6667 int pos = 0;
6668
6669 int outerDepth = parser.getDepth();
6670 int type;
6671 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6672 && (type != XmlPullParser.END_TAG
6673 || parser.getDepth() > outerDepth)) {
6674 if (type == XmlPullParser.END_TAG
6675 || type == XmlPullParser.TEXT) {
6676 continue;
6677 }
6678
6679 String tagName = parser.getName();
6680 if (tagName.equals("cert")) {
6681 if (pos < count) {
6682 String index = parser.getAttributeValue(null, "index");
6683 if (index != null) {
6684 try {
6685 int idx = Integer.parseInt(index);
6686 String key = parser.getAttributeValue(null, "key");
6687 if (key == null) {
6688 if (idx >= 0 && idx < pastSignatures.size()) {
6689 Signature sig = pastSignatures.get(idx);
6690 if (sig != null) {
6691 mSignatures[pos] = pastSignatures.get(idx);
6692 pos++;
6693 } else {
6694 reportSettingsProblem(Log.WARN,
6695 "Error in package manager settings: <cert> "
6696 + "index " + index + " is not defined at "
6697 + parser.getPositionDescription());
6698 }
6699 } else {
6700 reportSettingsProblem(Log.WARN,
6701 "Error in package manager settings: <cert> "
6702 + "index " + index + " is out of bounds at "
6703 + parser.getPositionDescription());
6704 }
6705 } else {
6706 while (pastSignatures.size() <= idx) {
6707 pastSignatures.add(null);
6708 }
6709 Signature sig = new Signature(key);
6710 pastSignatures.set(idx, sig);
6711 mSignatures[pos] = sig;
6712 pos++;
6713 }
6714 } catch (NumberFormatException e) {
6715 reportSettingsProblem(Log.WARN,
6716 "Error in package manager settings: <cert> "
6717 + "index " + index + " is not a number at "
6718 + parser.getPositionDescription());
6719 }
6720 } else {
6721 reportSettingsProblem(Log.WARN,
6722 "Error in package manager settings: <cert> has"
6723 + " no index at " + parser.getPositionDescription());
6724 }
6725 } else {
6726 reportSettingsProblem(Log.WARN,
6727 "Error in package manager settings: too "
6728 + "many <cert> tags, expected " + count
6729 + " at " + parser.getPositionDescription());
6730 }
6731 } else {
6732 reportSettingsProblem(Log.WARN,
6733 "Unknown element under <cert>: "
6734 + parser.getName());
6735 }
6736 XmlUtils.skipCurrentTag(parser);
6737 }
6738
6739 if (pos < count) {
6740 // Should never happen -- there is an error in the written
6741 // settings -- but if it does we don't want to generate
6742 // a bad array.
6743 Signature[] newSigs = new Signature[pos];
6744 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
6745 mSignatures = newSigs;
6746 }
6747 }
6748
6749 /**
6750 * If any of the given 'sigs' is contained in the existing signatures,
6751 * then completely replace the current signatures with the ones in
6752 * 'sigs'. This is used for updating an existing package to a newly
6753 * installed version.
6754 */
6755 boolean updateSignatures(Signature[] sigs, boolean update) {
6756 if (mSignatures == null) {
6757 if (update) {
6758 assignSignatures(sigs);
6759 }
6760 return true;
6761 }
6762 if (sigs == null) {
6763 return false;
6764 }
6765
6766 for (int i=0; i<sigs.length; i++) {
6767 Signature sig = sigs[i];
6768 for (int j=0; j<mSignatures.length; j++) {
6769 if (mSignatures[j].equals(sig)) {
6770 if (update) {
6771 assignSignatures(sigs);
6772 }
6773 return true;
6774 }
6775 }
6776 }
6777 return false;
6778 }
6779
6780 /**
6781 * If any of the given 'sigs' is contained in the existing signatures,
6782 * then add in any new signatures found in 'sigs'. This is used for
6783 * including a new package into an existing shared user id.
6784 */
6785 boolean mergeSignatures(Signature[] sigs, boolean update) {
6786 if (mSignatures == null) {
6787 if (update) {
6788 assignSignatures(sigs);
6789 }
6790 return true;
6791 }
6792 if (sigs == null) {
6793 return false;
6794 }
6795
6796 Signature[] added = null;
6797 int addedCount = 0;
6798 boolean haveMatch = false;
6799 for (int i=0; i<sigs.length; i++) {
6800 Signature sig = sigs[i];
6801 boolean found = false;
6802 for (int j=0; j<mSignatures.length; j++) {
6803 if (mSignatures[j].equals(sig)) {
6804 found = true;
6805 haveMatch = true;
6806 break;
6807 }
6808 }
6809
6810 if (!found) {
6811 if (added == null) {
6812 added = new Signature[sigs.length];
6813 }
6814 added[i] = sig;
6815 addedCount++;
6816 }
6817 }
6818
6819 if (!haveMatch) {
6820 // Nothing matched -- reject the new signatures.
6821 return false;
6822 }
6823 if (added == null) {
6824 // Completely matched -- nothing else to do.
6825 return true;
6826 }
6827
6828 // Add additional signatures in.
6829 if (update) {
6830 Signature[] total = new Signature[addedCount+mSignatures.length];
6831 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6832 int j = mSignatures.length;
6833 for (int i=0; i<added.length; i++) {
6834 if (added[i] != null) {
6835 total[j] = added[i];
6836 j++;
6837 }
6838 }
6839 mSignatures = total;
6840 }
6841 return true;
6842 }
6843
6844 private void assignSignatures(Signature[] sigs) {
6845 if (sigs == null) {
6846 mSignatures = null;
6847 return;
6848 }
6849 mSignatures = new Signature[sigs.length];
6850 for (int i=0; i<sigs.length; i++) {
6851 mSignatures[i] = sigs[i];
6852 }
6853 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 @Override
6856 public String toString() {
6857 StringBuffer buf = new StringBuffer(128);
6858 buf.append("PackageSignatures{");
6859 buf.append(Integer.toHexString(System.identityHashCode(this)));
6860 buf.append(" [");
6861 if (mSignatures != null) {
6862 for (int i=0; i<mSignatures.length; i++) {
6863 if (i > 0) buf.append(", ");
6864 buf.append(Integer.toHexString(
6865 System.identityHashCode(mSignatures[i])));
6866 }
6867 }
6868 buf.append("]}");
6869 return buf.toString();
6870 }
6871 }
6872
6873 static class PreferredActivity extends IntentFilter {
6874 final int mMatch;
6875 final String[] mSetPackages;
6876 final String[] mSetClasses;
6877 final String[] mSetComponents;
6878 final ComponentName mActivity;
6879 final String mShortActivity;
6880 String mParseError;
6881
6882 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6883 ComponentName activity) {
6884 super(filter);
6885 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6886 mActivity = activity;
6887 mShortActivity = activity.flattenToShortString();
6888 mParseError = null;
6889 if (set != null) {
6890 final int N = set.length;
6891 String[] myPackages = new String[N];
6892 String[] myClasses = new String[N];
6893 String[] myComponents = new String[N];
6894 for (int i=0; i<N; i++) {
6895 ComponentName cn = set[i];
6896 if (cn == null) {
6897 mSetPackages = null;
6898 mSetClasses = null;
6899 mSetComponents = null;
6900 return;
6901 }
6902 myPackages[i] = cn.getPackageName().intern();
6903 myClasses[i] = cn.getClassName().intern();
6904 myComponents[i] = cn.flattenToShortString().intern();
6905 }
6906 mSetPackages = myPackages;
6907 mSetClasses = myClasses;
6908 mSetComponents = myComponents;
6909 } else {
6910 mSetPackages = null;
6911 mSetClasses = null;
6912 mSetComponents = null;
6913 }
6914 }
6915
6916 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
6917 IOException {
6918 mShortActivity = parser.getAttributeValue(null, "name");
6919 mActivity = ComponentName.unflattenFromString(mShortActivity);
6920 if (mActivity == null) {
6921 mParseError = "Bad activity name " + mShortActivity;
6922 }
6923 String matchStr = parser.getAttributeValue(null, "match");
6924 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
6925 String setCountStr = parser.getAttributeValue(null, "set");
6926 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
6927
6928 String[] myPackages = setCount > 0 ? new String[setCount] : null;
6929 String[] myClasses = setCount > 0 ? new String[setCount] : null;
6930 String[] myComponents = setCount > 0 ? new String[setCount] : null;
6931
6932 int setPos = 0;
6933
6934 int outerDepth = parser.getDepth();
6935 int type;
6936 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6937 && (type != XmlPullParser.END_TAG
6938 || parser.getDepth() > outerDepth)) {
6939 if (type == XmlPullParser.END_TAG
6940 || type == XmlPullParser.TEXT) {
6941 continue;
6942 }
6943
6944 String tagName = parser.getName();
6945 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
6946 // + parser.getDepth() + " tag=" + tagName);
6947 if (tagName.equals("set")) {
6948 String name = parser.getAttributeValue(null, "name");
6949 if (name == null) {
6950 if (mParseError == null) {
6951 mParseError = "No name in set tag in preferred activity "
6952 + mShortActivity;
6953 }
6954 } else if (setPos >= setCount) {
6955 if (mParseError == null) {
6956 mParseError = "Too many set tags in preferred activity "
6957 + mShortActivity;
6958 }
6959 } else {
6960 ComponentName cn = ComponentName.unflattenFromString(name);
6961 if (cn == null) {
6962 if (mParseError == null) {
6963 mParseError = "Bad set name " + name + " in preferred activity "
6964 + mShortActivity;
6965 }
6966 } else {
6967 myPackages[setPos] = cn.getPackageName();
6968 myClasses[setPos] = cn.getClassName();
6969 myComponents[setPos] = name;
6970 setPos++;
6971 }
6972 }
6973 XmlUtils.skipCurrentTag(parser);
6974 } else if (tagName.equals("filter")) {
6975 //Log.i(TAG, "Starting to parse filter...");
6976 readFromXml(parser);
6977 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
6978 // + parser.getDepth() + " tag=" + parser.getName());
6979 } else {
6980 reportSettingsProblem(Log.WARN,
6981 "Unknown element under <preferred-activities>: "
6982 + parser.getName());
6983 XmlUtils.skipCurrentTag(parser);
6984 }
6985 }
6986
6987 if (setPos != setCount) {
6988 if (mParseError == null) {
6989 mParseError = "Not enough set tags (expected " + setCount
6990 + " but found " + setPos + ") in " + mShortActivity;
6991 }
6992 }
6993
6994 mSetPackages = myPackages;
6995 mSetClasses = myClasses;
6996 mSetComponents = myComponents;
6997 }
6998
6999 public void writeToXml(XmlSerializer serializer) throws IOException {
7000 final int NS = mSetClasses != null ? mSetClasses.length : 0;
7001 serializer.attribute(null, "name", mShortActivity);
7002 serializer.attribute(null, "match", Integer.toHexString(mMatch));
7003 serializer.attribute(null, "set", Integer.toString(NS));
7004 for (int s=0; s<NS; s++) {
7005 serializer.startTag(null, "set");
7006 serializer.attribute(null, "name", mSetComponents[s]);
7007 serializer.endTag(null, "set");
7008 }
7009 serializer.startTag(null, "filter");
7010 super.writeToXml(serializer);
7011 serializer.endTag(null, "filter");
7012 }
7013
7014 boolean sameSet(List<ResolveInfo> query, int priority) {
7015 if (mSetPackages == null) return false;
7016 final int NQ = query.size();
7017 final int NS = mSetPackages.length;
7018 int numMatch = 0;
7019 for (int i=0; i<NQ; i++) {
7020 ResolveInfo ri = query.get(i);
7021 if (ri.priority != priority) continue;
7022 ActivityInfo ai = ri.activityInfo;
7023 boolean good = false;
7024 for (int j=0; j<NS; j++) {
7025 if (mSetPackages[j].equals(ai.packageName)
7026 && mSetClasses[j].equals(ai.name)) {
7027 numMatch++;
7028 good = true;
7029 break;
7030 }
7031 }
7032 if (!good) return false;
7033 }
7034 return numMatch == NS;
7035 }
7036 }
7037
7038 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007039 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 HashSet<String> grantedPermissions = new HashSet<String>();
7042 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007047 setFlags(pkgFlags);
7048 }
7049
7050 void setFlags(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007051 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007052 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
7053 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 }
7055 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 /**
7058 * Settings base class for pending and resolved classes.
7059 */
7060 static class PackageSettingBase extends GrantedPermissions {
7061 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007062 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007063 File codePath;
7064 String codePathString;
7065 File resourcePath;
7066 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 private long timeStamp;
7068 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007069 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007071 boolean uidError;
7072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007073 PackageSignatures signatures = new PackageSignatures();
7074
7075 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007077 /* Explicitly disabled components */
7078 HashSet<String> disabledComponents = new HashSet<String>(0);
7079 /* Explicitly enabled components */
7080 HashSet<String> enabledComponents = new HashSet<String>(0);
7081 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7082 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007083
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007084 PackageSettingBase origPackage;
7085
Jacek Surazski65e13172009-04-28 15:26:38 +02007086 /* package name of the app that installed this package */
7087 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007089 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007090 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007091 super(pkgFlags);
7092 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007093 this.realName = realName;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007094 init(codePath, resourcePath, pVersionCode);
7095 }
7096
7097 void init(File codePath, File resourcePath, int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098 this.codePath = codePath;
7099 this.codePathString = codePath.toString();
7100 this.resourcePath = resourcePath;
7101 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007102 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007104
Jacek Surazski65e13172009-04-28 15:26:38 +02007105 public void setInstallerPackageName(String packageName) {
7106 installerPackageName = packageName;
7107 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007108
Jacek Surazski65e13172009-04-28 15:26:38 +02007109 String getInstallerPackageName() {
7110 return installerPackageName;
7111 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007113 public void setInstallStatus(int newStatus) {
7114 installStatus = newStatus;
7115 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 public int getInstallStatus() {
7118 return installStatus;
7119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007121 public void setTimeStamp(long newStamp) {
7122 if (newStamp != timeStamp) {
7123 timeStamp = newStamp;
7124 timeStampString = Long.toString(newStamp);
7125 }
7126 }
7127
7128 public void setTimeStamp(long newStamp, String newStampStr) {
7129 timeStamp = newStamp;
7130 timeStampString = newStampStr;
7131 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007133 public long getTimeStamp() {
7134 return timeStamp;
7135 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 public String getTimeStampStr() {
7138 return timeStampString;
7139 }
7140
7141 public void copyFrom(PackageSettingBase base) {
7142 grantedPermissions = base.grantedPermissions;
7143 gids = base.gids;
7144 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007146 timeStamp = base.timeStamp;
7147 timeStampString = base.timeStampString;
7148 signatures = base.signatures;
7149 permissionsFixed = base.permissionsFixed;
7150 disabledComponents = base.disabledComponents;
7151 enabledComponents = base.enabledComponents;
7152 enabled = base.enabled;
7153 installStatus = base.installStatus;
7154 }
7155
7156 void enableComponentLP(String componentClassName) {
7157 disabledComponents.remove(componentClassName);
7158 enabledComponents.add(componentClassName);
7159 }
7160
7161 void disableComponentLP(String componentClassName) {
7162 enabledComponents.remove(componentClassName);
7163 disabledComponents.add(componentClassName);
7164 }
7165
7166 void restoreComponentLP(String componentClassName) {
7167 enabledComponents.remove(componentClassName);
7168 disabledComponents.remove(componentClassName);
7169 }
7170
7171 int currentEnabledStateLP(String componentName) {
7172 if (enabledComponents.contains(componentName)) {
7173 return COMPONENT_ENABLED_STATE_ENABLED;
7174 } else if (disabledComponents.contains(componentName)) {
7175 return COMPONENT_ENABLED_STATE_DISABLED;
7176 } else {
7177 return COMPONENT_ENABLED_STATE_DEFAULT;
7178 }
7179 }
7180 }
7181
7182 /**
7183 * Settings data for a particular package we know about.
7184 */
7185 static final class PackageSetting extends PackageSettingBase {
7186 int userId;
7187 PackageParser.Package pkg;
7188 SharedUserSetting sharedUser;
7189
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007190 PackageSetting(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007191 int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007192 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007193 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 @Override
7196 public String toString() {
7197 return "PackageSetting{"
7198 + Integer.toHexString(System.identityHashCode(this))
7199 + " " + name + "/" + userId + "}";
7200 }
7201 }
7202
7203 /**
7204 * Settings data for a particular shared user ID we know about.
7205 */
7206 static final class SharedUserSetting extends GrantedPermissions {
7207 final String name;
7208 int userId;
7209 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
7210 final PackageSignatures signatures = new PackageSignatures();
7211
7212 SharedUserSetting(String _name, int _pkgFlags) {
7213 super(_pkgFlags);
7214 name = _name;
7215 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 @Override
7218 public String toString() {
7219 return "SharedUserSetting{"
7220 + Integer.toHexString(System.identityHashCode(this))
7221 + " " + name + "/" + userId + "}";
7222 }
7223 }
7224
7225 /**
7226 * Holds information about dynamic settings.
7227 */
7228 private static final class Settings {
7229 private final File mSettingsFilename;
7230 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007231 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 private final HashMap<String, PackageSetting> mPackages =
7233 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 // List of replaced system applications
7235 final HashMap<String, PackageSetting> mDisabledSysPackages =
7236 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 // The user's preferred activities associated with particular intent
7239 // filters.
7240 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
7241 new IntentResolver<PreferredActivity, PreferredActivity>() {
7242 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007243 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007245 out.print(prefix); out.print(
7246 Integer.toHexString(System.identityHashCode(filter)));
7247 out.print(' ');
7248 out.print(filter.mActivity.flattenToShortString());
7249 out.print(" match=0x");
7250 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007252 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007253 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007254 out.print(prefix); out.print(" ");
7255 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007256 }
7257 }
7258 }
7259 };
7260 private final HashMap<String, SharedUserSetting> mSharedUsers =
7261 new HashMap<String, SharedUserSetting>();
7262 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
7263 private final SparseArray<Object> mOtherUserIds =
7264 new SparseArray<Object>();
7265
7266 // For reading/writing settings file.
7267 private final ArrayList<Signature> mPastSignatures =
7268 new ArrayList<Signature>();
7269
7270 // Mapping from permission names to info about them.
7271 final HashMap<String, BasePermission> mPermissions =
7272 new HashMap<String, BasePermission>();
7273
7274 // Mapping from permission tree names to info about them.
7275 final HashMap<String, BasePermission> mPermissionTrees =
7276 new HashMap<String, BasePermission>();
7277
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007278 // Packages that have been uninstalled and still need their external
7279 // storage data deleted.
7280 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
7281
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007282 // Packages that have been renamed since they were first installed.
7283 // Keys are the new names of the packages, values are the original
7284 // names. The packages appear everwhere else under their original
7285 // names.
7286 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
7287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007288 private final StringBuilder mReadMessages = new StringBuilder();
7289
7290 private static final class PendingPackage extends PackageSettingBase {
7291 final int sharedId;
7292
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007293 PendingPackage(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007294 int sharedId, int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007295 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007296 this.sharedId = sharedId;
7297 }
7298 }
7299 private final ArrayList<PendingPackage> mPendingPackages
7300 = new ArrayList<PendingPackage>();
7301
7302 Settings() {
7303 File dataDir = Environment.getDataDirectory();
7304 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08007305 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
7306 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007308 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 FileUtils.setPermissions(systemDir.toString(),
7310 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7311 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7312 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08007313 FileUtils.setPermissions(systemSecureDir.toString(),
7314 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7315 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7316 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 mSettingsFilename = new File(systemDir, "packages.xml");
7318 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007319 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 }
7321
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007322 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007323 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 int pkgFlags, boolean create, boolean add) {
7325 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007326 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007327 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007328 return p;
7329 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007330
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007331 PackageSetting peekPackageLP(String name) {
7332 return mPackages.get(name);
7333 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007334 PackageSetting p = mPackages.get(name);
7335 if (p != null && p.codePath.getPath().equals(codePath)) {
7336 return p;
7337 }
7338 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007339 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007340 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 void setInstallStatus(String pkgName, int status) {
7343 PackageSetting p = mPackages.get(pkgName);
7344 if(p != null) {
7345 if(p.getInstallStatus() != status) {
7346 p.setInstallStatus(status);
7347 }
7348 }
7349 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007350
Jacek Surazski65e13172009-04-28 15:26:38 +02007351 void setInstallerPackageName(String pkgName,
7352 String installerPkgName) {
7353 PackageSetting p = mPackages.get(pkgName);
7354 if(p != null) {
7355 p.setInstallerPackageName(installerPkgName);
7356 }
7357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007358
Jacek Surazski65e13172009-04-28 15:26:38 +02007359 String getInstallerPackageName(String pkgName) {
7360 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007361 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02007362 }
7363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364 int getInstallStatus(String pkgName) {
7365 PackageSetting p = mPackages.get(pkgName);
7366 if(p != null) {
7367 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007369 return -1;
7370 }
7371
7372 SharedUserSetting getSharedUserLP(String name,
7373 int pkgFlags, boolean create) {
7374 SharedUserSetting s = mSharedUsers.get(name);
7375 if (s == null) {
7376 if (!create) {
7377 return null;
7378 }
7379 s = new SharedUserSetting(name, pkgFlags);
7380 if (MULTIPLE_APPLICATION_UIDS) {
7381 s.userId = newUserIdLP(s);
7382 } else {
7383 s.userId = FIRST_APPLICATION_UID;
7384 }
7385 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
7386 // < 0 means we couldn't assign a userid; fall out and return
7387 // s, which is currently null
7388 if (s.userId >= 0) {
7389 mSharedUsers.put(name, s);
7390 }
7391 }
7392
7393 return s;
7394 }
7395
7396 int disableSystemPackageLP(String name) {
7397 PackageSetting p = mPackages.get(name);
7398 if(p == null) {
7399 Log.w(TAG, "Package:"+name+" is not an installed package");
7400 return -1;
7401 }
7402 PackageSetting dp = mDisabledSysPackages.get(name);
7403 // always make sure the system package code and resource paths dont change
7404 if(dp == null) {
7405 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7406 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7407 }
7408 mDisabledSysPackages.put(name, p);
7409 }
7410 return removePackageLP(name);
7411 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 PackageSetting enableSystemPackageLP(String name) {
7414 PackageSetting p = mDisabledSysPackages.get(name);
7415 if(p == null) {
7416 Log.w(TAG, "Package:"+name+" is not disabled");
7417 return null;
7418 }
7419 // Reset flag in ApplicationInfo object
7420 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7421 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7422 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007423 PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007424 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007425 mDisabledSysPackages.remove(name);
7426 return ret;
7427 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007428
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007429 PackageSetting addPackageLP(String name, String realName, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007430 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007431 PackageSetting p = mPackages.get(name);
7432 if (p != null) {
7433 if (p.userId == uid) {
7434 return p;
7435 }
7436 reportSettingsProblem(Log.ERROR,
7437 "Adding duplicate package, keeping first: " + name);
7438 return null;
7439 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007440 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 p.userId = uid;
7442 if (addUserIdLP(uid, p, name)) {
7443 mPackages.put(name, p);
7444 return p;
7445 }
7446 return null;
7447 }
7448
7449 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
7450 SharedUserSetting s = mSharedUsers.get(name);
7451 if (s != null) {
7452 if (s.userId == uid) {
7453 return s;
7454 }
7455 reportSettingsProblem(Log.ERROR,
7456 "Adding duplicate shared user, keeping first: " + name);
7457 return null;
7458 }
7459 s = new SharedUserSetting(name, pkgFlags);
7460 s.userId = uid;
7461 if (addUserIdLP(uid, s, name)) {
7462 mSharedUsers.put(name, s);
7463 return s;
7464 }
7465 return null;
7466 }
7467
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007468 // Transfer ownership of permissions from one package to another.
7469 private void transferPermissions(String origPkg, String newPkg) {
7470 // Transfer ownership of permissions to the new package.
7471 for (int i=0; i<2; i++) {
7472 HashMap<String, BasePermission> permissions =
7473 i == 0 ? mPermissionTrees : mPermissions;
7474 for (BasePermission bp : permissions.values()) {
7475 if (origPkg.equals(bp.sourcePackage)) {
7476 if (DEBUG_UPGRADE) Log.v(TAG,
7477 "Moving permission " + bp.name
7478 + " from pkg " + bp.sourcePackage
7479 + " to " + newPkg);
7480 bp.sourcePackage = newPkg;
7481 bp.perm = null;
7482 if (bp.pendingInfo != null) {
7483 bp.sourcePackage = newPkg;
7484 }
7485 bp.uid = 0;
7486 bp.gids = null;
7487 }
7488 }
7489 }
7490 }
7491
7492 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007493 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007494 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 PackageSetting p = mPackages.get(name);
7496 if (p != null) {
7497 if (!p.codePath.equals(codePath)) {
7498 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007499 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007500 // This is an updated system app with versions in both system
7501 // and data partition. Just let the most recent version
7502 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007503 Log.w(TAG, "Trying to update system app code path from " +
7504 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007505 } else {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007506 // Just a change in the code path is not an issue, but
7507 // let's log a message about it.
7508 Log.i(TAG, "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007509 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007511 }
7512 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 reportSettingsProblem(Log.WARN,
7514 "Package " + name + " shared user changed from "
7515 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
7516 + " to "
7517 + (sharedUser != null ? sharedUser.name : "<nothing>")
7518 + "; replacing with new");
7519 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007520 } else {
7521 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7522 // If what we are scanning is a system package, then
7523 // make it so, regardless of whether it was previously
7524 // installed only in the data partition.
7525 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 }
7528 }
7529 if (p == null) {
7530 // Create a new PackageSettings entry. this can end up here because
7531 // of code path mismatch or user id mismatch of an updated system partition
7532 if (!create) {
7533 return null;
7534 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007535 if (origPackage != null) {
7536 // We are consuming the data from an existing package.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007537 p = new PackageSetting(origPackage.name, name, codePath,
7538 resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007539 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
7540 + " is adopting original package " + origPackage.name);
7541 p.copyFrom(origPackage);
7542 p.sharedUser = origPackage.sharedUser;
7543 p.userId = origPackage.userId;
7544 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007545 mRenamedPackages.put(name, origPackage.name);
7546 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007547 // Update new package state.
7548 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007550 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007551 p.setTimeStamp(codePath.lastModified());
7552 p.sharedUser = sharedUser;
7553 if (sharedUser != null) {
7554 p.userId = sharedUser.userId;
7555 } else if (MULTIPLE_APPLICATION_UIDS) {
7556 // Clone the setting here for disabled system packages
7557 PackageSetting dis = mDisabledSysPackages.get(name);
7558 if (dis != null) {
7559 // For disabled packages a new setting is created
7560 // from the existing user id. This still has to be
7561 // added to list of user id's
7562 // Copy signatures from previous setting
7563 if (dis.signatures.mSignatures != null) {
7564 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
7565 }
7566 p.userId = dis.userId;
7567 // Clone permissions
7568 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
7569 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
7570 // Clone component info
7571 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
7572 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
7573 // Add new setting to list of user ids
7574 addUserIdLP(p.userId, p, name);
7575 } else {
7576 // Assign new user id
7577 p.userId = newUserIdLP(p);
7578 }
7579 } else {
7580 p.userId = FIRST_APPLICATION_UID;
7581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 }
7583 if (p.userId < 0) {
7584 reportSettingsProblem(Log.WARN,
7585 "Package " + name + " could not be assigned a valid uid");
7586 return null;
7587 }
7588 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007589 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007591 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 }
7593 }
7594 return p;
7595 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007596
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007597 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007598 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007599 String codePath = pkg.applicationInfo.sourceDir;
7600 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007601 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007602 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007603 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007604 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007605 p.codePath = new File(codePath);
7606 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007607 }
7608 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007609 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007610 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007611 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007612 p.resourcePath = new File(resourcePath);
7613 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007614 }
7615 // Update version code if needed
7616 if (pkg.mVersionCode != p.versionCode) {
7617 p.versionCode = pkg.mVersionCode;
7618 }
7619 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
7620 }
7621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007622 // Utility method that adds a PackageSetting to mPackages and
7623 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007624 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 SharedUserSetting sharedUser) {
7626 mPackages.put(name, p);
7627 if (sharedUser != null) {
7628 if (p.sharedUser != null && p.sharedUser != sharedUser) {
7629 reportSettingsProblem(Log.ERROR,
7630 "Package " + p.name + " was user "
7631 + p.sharedUser + " but is now " + sharedUser
7632 + "; I am not changing its files so it will probably fail!");
7633 p.sharedUser.packages.remove(p);
7634 } else if (p.userId != sharedUser.userId) {
7635 reportSettingsProblem(Log.ERROR,
7636 "Package " + p.name + " was user id " + p.userId
7637 + " but is now user " + sharedUser
7638 + " with id " + sharedUser.userId
7639 + "; I am not changing its files so it will probably fail!");
7640 }
7641
7642 sharedUser.packages.add(p);
7643 p.sharedUser = sharedUser;
7644 p.userId = sharedUser.userId;
7645 }
7646 }
7647
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007648 /*
7649 * Update the shared user setting when a package using
7650 * specifying the shared user id is removed. The gids
7651 * associated with each permission of the deleted package
7652 * are removed from the shared user's gid list only if its
7653 * not in use by other permissions of packages in the
7654 * shared user setting.
7655 */
7656 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
7658 Log.i(TAG, "Trying to update info for null package. Just ignoring");
7659 return;
7660 }
7661 // No sharedUserId
7662 if (deletedPs.sharedUser == null) {
7663 return;
7664 }
7665 SharedUserSetting sus = deletedPs.sharedUser;
7666 // Update permissions
7667 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
7668 boolean used = false;
7669 if (!sus.grantedPermissions.contains (eachPerm)) {
7670 continue;
7671 }
7672 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007673 if (pkg.pkg != null &&
7674 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
7675 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 used = true;
7677 break;
7678 }
7679 }
7680 if (!used) {
7681 // can safely delete this permission from list
7682 sus.grantedPermissions.remove(eachPerm);
7683 sus.loadedPermissions.remove(eachPerm);
7684 }
7685 }
7686 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007687 int newGids[] = globalGids;
7688 for (String eachPerm : sus.grantedPermissions) {
7689 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007690 if (bp != null) {
7691 newGids = appendInts(newGids, bp.gids);
7692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007693 }
7694 sus.gids = newGids;
7695 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007697 private int removePackageLP(String name) {
7698 PackageSetting p = mPackages.get(name);
7699 if (p != null) {
7700 mPackages.remove(name);
7701 if (p.sharedUser != null) {
7702 p.sharedUser.packages.remove(p);
7703 if (p.sharedUser.packages.size() == 0) {
7704 mSharedUsers.remove(p.sharedUser.name);
7705 removeUserIdLP(p.sharedUser.userId);
7706 return p.sharedUser.userId;
7707 }
7708 } else {
7709 removeUserIdLP(p.userId);
7710 return p.userId;
7711 }
7712 }
7713 return -1;
7714 }
7715
7716 private boolean addUserIdLP(int uid, Object obj, Object name) {
7717 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
7718 return false;
7719 }
7720
7721 if (uid >= FIRST_APPLICATION_UID) {
7722 int N = mUserIds.size();
7723 final int index = uid - FIRST_APPLICATION_UID;
7724 while (index >= N) {
7725 mUserIds.add(null);
7726 N++;
7727 }
7728 if (mUserIds.get(index) != null) {
7729 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007730 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 + " name=" + name);
7732 return false;
7733 }
7734 mUserIds.set(index, obj);
7735 } else {
7736 if (mOtherUserIds.get(uid) != null) {
7737 reportSettingsProblem(Log.ERROR,
7738 "Adding duplicate shared id: " + uid
7739 + " name=" + name);
7740 return false;
7741 }
7742 mOtherUserIds.put(uid, obj);
7743 }
7744 return true;
7745 }
7746
7747 public Object getUserIdLP(int uid) {
7748 if (uid >= FIRST_APPLICATION_UID) {
7749 int N = mUserIds.size();
7750 final int index = uid - FIRST_APPLICATION_UID;
7751 return index < N ? mUserIds.get(index) : null;
7752 } else {
7753 return mOtherUserIds.get(uid);
7754 }
7755 }
7756
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007757 private Set<String> findPackagesWithFlag(int flag) {
7758 Set<String> ret = new HashSet<String>();
7759 for (PackageSetting ps : mPackages.values()) {
7760 // Has to match atleast all the flag bits set on flag
7761 if ((ps.pkgFlags & flag) == flag) {
7762 ret.add(ps.name);
7763 }
7764 }
7765 return ret;
7766 }
7767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 private void removeUserIdLP(int uid) {
7769 if (uid >= FIRST_APPLICATION_UID) {
7770 int N = mUserIds.size();
7771 final int index = uid - FIRST_APPLICATION_UID;
7772 if (index < N) mUserIds.set(index, null);
7773 } else {
7774 mOtherUserIds.remove(uid);
7775 }
7776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007778 void writeLP() {
7779 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
7780
7781 // Keep the old settings around until we know the new ones have
7782 // been successfully written.
7783 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007784 // Presence of backup settings file indicates that we failed
7785 // to persist settings earlier. So preserve the older
7786 // backup for future reference since the current settings
7787 // might have been corrupted.
7788 if (!mBackupSettingsFilename.exists()) {
7789 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
7790 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
7791 return;
7792 }
7793 } else {
7794 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07007795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007796 }
7797
7798 mPastSignatures.clear();
7799
7800 try {
7801 FileOutputStream str = new FileOutputStream(mSettingsFilename);
7802
7803 //XmlSerializer serializer = XmlUtils.serializerInstance();
7804 XmlSerializer serializer = new FastXmlSerializer();
7805 serializer.setOutput(str, "utf-8");
7806 serializer.startDocument(null, true);
7807 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
7808
7809 serializer.startTag(null, "packages");
7810
7811 serializer.startTag(null, "permission-trees");
7812 for (BasePermission bp : mPermissionTrees.values()) {
7813 writePermission(serializer, bp);
7814 }
7815 serializer.endTag(null, "permission-trees");
7816
7817 serializer.startTag(null, "permissions");
7818 for (BasePermission bp : mPermissions.values()) {
7819 writePermission(serializer, bp);
7820 }
7821 serializer.endTag(null, "permissions");
7822
7823 for (PackageSetting pkg : mPackages.values()) {
7824 writePackage(serializer, pkg);
7825 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7828 writeDisabledSysPackage(serializer, pkg);
7829 }
7830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 serializer.startTag(null, "preferred-activities");
7832 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7833 serializer.startTag(null, "item");
7834 pa.writeToXml(serializer);
7835 serializer.endTag(null, "item");
7836 }
7837 serializer.endTag(null, "preferred-activities");
7838
7839 for (SharedUserSetting usr : mSharedUsers.values()) {
7840 serializer.startTag(null, "shared-user");
7841 serializer.attribute(null, "name", usr.name);
7842 serializer.attribute(null, "userId",
7843 Integer.toString(usr.userId));
7844 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7845 serializer.startTag(null, "perms");
7846 for (String name : usr.grantedPermissions) {
7847 serializer.startTag(null, "item");
7848 serializer.attribute(null, "name", name);
7849 serializer.endTag(null, "item");
7850 }
7851 serializer.endTag(null, "perms");
7852 serializer.endTag(null, "shared-user");
7853 }
7854
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007855 if (mPackagesToBeCleaned.size() > 0) {
7856 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
7857 serializer.startTag(null, "cleaning-package");
7858 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
7859 serializer.endTag(null, "cleaning-package");
7860 }
7861 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007862
7863 if (mRenamedPackages.size() > 0) {
7864 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
7865 serializer.startTag(null, "renamed-package");
7866 serializer.attribute(null, "new", e.getKey());
7867 serializer.attribute(null, "old", e.getValue());
7868 serializer.endTag(null, "renamed-package");
7869 }
7870 }
7871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 serializer.endTag(null, "packages");
7873
7874 serializer.endDocument();
7875
7876 str.flush();
7877 str.close();
7878
7879 // New settings successfully written, old ones are no longer
7880 // needed.
7881 mBackupSettingsFilename.delete();
7882 FileUtils.setPermissions(mSettingsFilename.toString(),
7883 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7884 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7885 |FileUtils.S_IROTH,
7886 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007887
7888 // Write package list file now, use a JournaledFile.
7889 //
7890 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
7891 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
7892
7893 str = new FileOutputStream(journal.chooseForWrite());
7894 try {
7895 StringBuilder sb = new StringBuilder();
7896 for (PackageSetting pkg : mPackages.values()) {
7897 ApplicationInfo ai = pkg.pkg.applicationInfo;
7898 String dataPath = ai.dataDir;
7899 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
7900
7901 // Avoid any application that has a space in its path
7902 // or that is handled by the system.
7903 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
7904 continue;
7905
7906 // we store on each line the following information for now:
7907 //
7908 // pkgName - package name
7909 // userId - application-specific user id
7910 // debugFlag - 0 or 1 if the package is debuggable.
7911 // dataPath - path to package's data path
7912 //
7913 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
7914 //
7915 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
7916 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
7917 // system/core/run-as/run-as.c
7918 //
7919 sb.setLength(0);
7920 sb.append(ai.packageName);
7921 sb.append(" ");
7922 sb.append((int)ai.uid);
7923 sb.append(isDebug ? " 1 " : " 0 ");
7924 sb.append(dataPath);
7925 sb.append("\n");
7926 str.write(sb.toString().getBytes());
7927 }
7928 str.flush();
7929 str.close();
7930 journal.commit();
7931 }
7932 catch (Exception e) {
7933 journal.rollback();
7934 }
7935
7936 FileUtils.setPermissions(mPackageListFilename.toString(),
7937 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7938 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7939 |FileUtils.S_IROTH,
7940 -1, -1);
7941
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007942 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007943
7944 } catch(XmlPullParserException e) {
7945 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 } catch(java.io.IOException e) {
7947 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007949 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007950 if (mSettingsFilename.exists()) {
7951 if (!mSettingsFilename.delete()) {
7952 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
7953 }
7954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007955 //Debug.stopMethodTracing();
7956 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007957
7958 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007959 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007960 serializer.startTag(null, "updated-package");
7961 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007962 if (pkg.realName != null) {
7963 serializer.attribute(null, "realName", pkg.realName);
7964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965 serializer.attribute(null, "codePath", pkg.codePathString);
7966 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007967 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007968 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7969 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7970 }
7971 if (pkg.sharedUser == null) {
7972 serializer.attribute(null, "userId",
7973 Integer.toString(pkg.userId));
7974 } else {
7975 serializer.attribute(null, "sharedUserId",
7976 Integer.toString(pkg.userId));
7977 }
7978 serializer.startTag(null, "perms");
7979 if (pkg.sharedUser == null) {
7980 // If this is a shared user, the permissions will
7981 // be written there. We still need to write an
7982 // empty permissions list so permissionsFixed will
7983 // be set.
7984 for (final String name : pkg.grantedPermissions) {
7985 BasePermission bp = mPermissions.get(name);
7986 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
7987 // We only need to write signature or system permissions but this wont
7988 // match the semantics of grantedPermissions. So write all permissions.
7989 serializer.startTag(null, "item");
7990 serializer.attribute(null, "name", name);
7991 serializer.endTag(null, "item");
7992 }
7993 }
7994 }
7995 serializer.endTag(null, "perms");
7996 serializer.endTag(null, "updated-package");
7997 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007998
7999 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008000 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 serializer.startTag(null, "package");
8002 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008003 if (pkg.realName != null) {
8004 serializer.attribute(null, "realName", pkg.realName);
8005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 serializer.attribute(null, "codePath", pkg.codePathString);
8007 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8008 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8009 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008010 serializer.attribute(null, "flags",
8011 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008012 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008013 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 if (pkg.sharedUser == null) {
8015 serializer.attribute(null, "userId",
8016 Integer.toString(pkg.userId));
8017 } else {
8018 serializer.attribute(null, "sharedUserId",
8019 Integer.toString(pkg.userId));
8020 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008021 if (pkg.uidError) {
8022 serializer.attribute(null, "uidError", "true");
8023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
8025 serializer.attribute(null, "enabled",
8026 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
8027 ? "true" : "false");
8028 }
8029 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
8030 serializer.attribute(null, "installStatus", "false");
8031 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008032 if (pkg.installerPackageName != null) {
8033 serializer.attribute(null, "installer", pkg.installerPackageName);
8034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008035 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
8036 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8037 serializer.startTag(null, "perms");
8038 if (pkg.sharedUser == null) {
8039 // If this is a shared user, the permissions will
8040 // be written there. We still need to write an
8041 // empty permissions list so permissionsFixed will
8042 // be set.
8043 for (final String name : pkg.grantedPermissions) {
8044 serializer.startTag(null, "item");
8045 serializer.attribute(null, "name", name);
8046 serializer.endTag(null, "item");
8047 }
8048 }
8049 serializer.endTag(null, "perms");
8050 }
8051 if (pkg.disabledComponents.size() > 0) {
8052 serializer.startTag(null, "disabled-components");
8053 for (final String name : pkg.disabledComponents) {
8054 serializer.startTag(null, "item");
8055 serializer.attribute(null, "name", name);
8056 serializer.endTag(null, "item");
8057 }
8058 serializer.endTag(null, "disabled-components");
8059 }
8060 if (pkg.enabledComponents.size() > 0) {
8061 serializer.startTag(null, "enabled-components");
8062 for (final String name : pkg.enabledComponents) {
8063 serializer.startTag(null, "item");
8064 serializer.attribute(null, "name", name);
8065 serializer.endTag(null, "item");
8066 }
8067 serializer.endTag(null, "enabled-components");
8068 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008070 serializer.endTag(null, "package");
8071 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 void writePermission(XmlSerializer serializer, BasePermission bp)
8074 throws XmlPullParserException, java.io.IOException {
8075 if (bp.type != BasePermission.TYPE_BUILTIN
8076 && bp.sourcePackage != null) {
8077 serializer.startTag(null, "item");
8078 serializer.attribute(null, "name", bp.name);
8079 serializer.attribute(null, "package", bp.sourcePackage);
8080 if (DEBUG_SETTINGS) Log.v(TAG,
8081 "Writing perm: name=" + bp.name + " type=" + bp.type);
8082 if (bp.type == BasePermission.TYPE_DYNAMIC) {
8083 PermissionInfo pi = bp.perm != null ? bp.perm.info
8084 : bp.pendingInfo;
8085 if (pi != null) {
8086 serializer.attribute(null, "type", "dynamic");
8087 if (pi.icon != 0) {
8088 serializer.attribute(null, "icon",
8089 Integer.toString(pi.icon));
8090 }
8091 if (pi.nonLocalizedLabel != null) {
8092 serializer.attribute(null, "label",
8093 pi.nonLocalizedLabel.toString());
8094 }
8095 if (pi.protectionLevel !=
8096 PermissionInfo.PROTECTION_NORMAL) {
8097 serializer.attribute(null, "protection",
8098 Integer.toString(pi.protectionLevel));
8099 }
8100 }
8101 }
8102 serializer.endTag(null, "item");
8103 }
8104 }
8105
8106 String getReadMessagesLP() {
8107 return mReadMessages.toString();
8108 }
8109
Oscar Montemayora8529f62009-11-18 10:14:20 -08008110 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
8112 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008113 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 while(its.hasNext()) {
8115 String key = its.next();
8116 PackageSetting ps = mPackages.get(key);
8117 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08008118 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 }
8120 }
8121 return ret;
8122 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008124 boolean readLP() {
8125 FileInputStream str = null;
8126 if (mBackupSettingsFilename.exists()) {
8127 try {
8128 str = new FileInputStream(mBackupSettingsFilename);
8129 mReadMessages.append("Reading from backup settings file\n");
8130 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008131 if (mSettingsFilename.exists()) {
8132 // If both the backup and settings file exist, we
8133 // ignore the settings since it might have been
8134 // corrupted.
8135 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
8136 mSettingsFilename.delete();
8137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008138 } catch (java.io.IOException e) {
8139 // We'll try for the normal settings file.
8140 }
8141 }
8142
8143 mPastSignatures.clear();
8144
8145 try {
8146 if (str == null) {
8147 if (!mSettingsFilename.exists()) {
8148 mReadMessages.append("No settings file found\n");
8149 Log.i(TAG, "No current settings file!");
8150 return false;
8151 }
8152 str = new FileInputStream(mSettingsFilename);
8153 }
8154 XmlPullParser parser = Xml.newPullParser();
8155 parser.setInput(str, null);
8156
8157 int type;
8158 while ((type=parser.next()) != XmlPullParser.START_TAG
8159 && type != XmlPullParser.END_DOCUMENT) {
8160 ;
8161 }
8162
8163 if (type != XmlPullParser.START_TAG) {
8164 mReadMessages.append("No start tag found in settings file\n");
8165 Log.e(TAG, "No start tag found in package manager settings");
8166 return false;
8167 }
8168
8169 int outerDepth = parser.getDepth();
8170 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8171 && (type != XmlPullParser.END_TAG
8172 || parser.getDepth() > outerDepth)) {
8173 if (type == XmlPullParser.END_TAG
8174 || type == XmlPullParser.TEXT) {
8175 continue;
8176 }
8177
8178 String tagName = parser.getName();
8179 if (tagName.equals("package")) {
8180 readPackageLP(parser);
8181 } else if (tagName.equals("permissions")) {
8182 readPermissionsLP(mPermissions, parser);
8183 } else if (tagName.equals("permission-trees")) {
8184 readPermissionsLP(mPermissionTrees, parser);
8185 } else if (tagName.equals("shared-user")) {
8186 readSharedUserLP(parser);
8187 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08008188 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189 } else if (tagName.equals("preferred-activities")) {
8190 readPreferredActivitiesLP(parser);
8191 } else if(tagName.equals("updated-package")) {
8192 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008193 } else if (tagName.equals("cleaning-package")) {
8194 String name = parser.getAttributeValue(null, "name");
8195 if (name != null) {
8196 mPackagesToBeCleaned.add(name);
8197 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008198 } else if (tagName.equals("renamed-package")) {
8199 String nname = parser.getAttributeValue(null, "new");
8200 String oname = parser.getAttributeValue(null, "old");
8201 if (nname != null && oname != null) {
8202 mRenamedPackages.put(nname, oname);
8203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008204 } else {
8205 Log.w(TAG, "Unknown element under <packages>: "
8206 + parser.getName());
8207 XmlUtils.skipCurrentTag(parser);
8208 }
8209 }
8210
8211 str.close();
8212
8213 } catch(XmlPullParserException e) {
8214 mReadMessages.append("Error reading: " + e.toString());
8215 Log.e(TAG, "Error reading package manager settings", e);
8216
8217 } catch(java.io.IOException e) {
8218 mReadMessages.append("Error reading: " + e.toString());
8219 Log.e(TAG, "Error reading package manager settings", e);
8220
8221 }
8222
8223 int N = mPendingPackages.size();
8224 for (int i=0; i<N; i++) {
8225 final PendingPackage pp = mPendingPackages.get(i);
8226 Object idObj = getUserIdLP(pp.sharedId);
8227 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008228 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008230 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008231 if (p == null) {
8232 Log.w(TAG, "Unable to create application package for "
8233 + pp.name);
8234 continue;
8235 }
8236 p.copyFrom(pp);
8237 } else if (idObj != null) {
8238 String msg = "Bad package setting: package " + pp.name
8239 + " has shared uid " + pp.sharedId
8240 + " that is not a shared uid\n";
8241 mReadMessages.append(msg);
8242 Log.e(TAG, msg);
8243 } else {
8244 String msg = "Bad package setting: package " + pp.name
8245 + " has shared uid " + pp.sharedId
8246 + " that is not defined\n";
8247 mReadMessages.append(msg);
8248 Log.e(TAG, msg);
8249 }
8250 }
8251 mPendingPackages.clear();
8252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008253 mReadMessages.append("Read completed successfully: "
8254 + mPackages.size() + " packages, "
8255 + mSharedUsers.size() + " shared uids\n");
8256
8257 return true;
8258 }
8259
8260 private int readInt(XmlPullParser parser, String ns, String name,
8261 int defValue) {
8262 String v = parser.getAttributeValue(ns, name);
8263 try {
8264 if (v == null) {
8265 return defValue;
8266 }
8267 return Integer.parseInt(v);
8268 } catch (NumberFormatException e) {
8269 reportSettingsProblem(Log.WARN,
8270 "Error in package manager settings: attribute " +
8271 name + " has bad integer value " + v + " at "
8272 + parser.getPositionDescription());
8273 }
8274 return defValue;
8275 }
8276
8277 private void readPermissionsLP(HashMap<String, BasePermission> out,
8278 XmlPullParser parser)
8279 throws IOException, XmlPullParserException {
8280 int outerDepth = parser.getDepth();
8281 int type;
8282 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8283 && (type != XmlPullParser.END_TAG
8284 || parser.getDepth() > outerDepth)) {
8285 if (type == XmlPullParser.END_TAG
8286 || type == XmlPullParser.TEXT) {
8287 continue;
8288 }
8289
8290 String tagName = parser.getName();
8291 if (tagName.equals("item")) {
8292 String name = parser.getAttributeValue(null, "name");
8293 String sourcePackage = parser.getAttributeValue(null, "package");
8294 String ptype = parser.getAttributeValue(null, "type");
8295 if (name != null && sourcePackage != null) {
8296 boolean dynamic = "dynamic".equals(ptype);
8297 BasePermission bp = new BasePermission(name, sourcePackage,
8298 dynamic
8299 ? BasePermission.TYPE_DYNAMIC
8300 : BasePermission.TYPE_NORMAL);
8301 if (dynamic) {
8302 PermissionInfo pi = new PermissionInfo();
8303 pi.packageName = sourcePackage.intern();
8304 pi.name = name.intern();
8305 pi.icon = readInt(parser, null, "icon", 0);
8306 pi.nonLocalizedLabel = parser.getAttributeValue(
8307 null, "label");
8308 pi.protectionLevel = readInt(parser, null, "protection",
8309 PermissionInfo.PROTECTION_NORMAL);
8310 bp.pendingInfo = pi;
8311 }
8312 out.put(bp.name, bp);
8313 } else {
8314 reportSettingsProblem(Log.WARN,
8315 "Error in package manager settings: permissions has"
8316 + " no name at " + parser.getPositionDescription());
8317 }
8318 } else {
8319 reportSettingsProblem(Log.WARN,
8320 "Unknown element reading permissions: "
8321 + parser.getName() + " at "
8322 + parser.getPositionDescription());
8323 }
8324 XmlUtils.skipCurrentTag(parser);
8325 }
8326 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008329 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008330 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008331 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008332 String codePathStr = parser.getAttributeValue(null, "codePath");
8333 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008334 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 resourcePathStr = codePathStr;
8336 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008337 String version = parser.getAttributeValue(null, "version");
8338 int versionCode = 0;
8339 if (version != null) {
8340 try {
8341 versionCode = Integer.parseInt(version);
8342 } catch (NumberFormatException e) {
8343 }
8344 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008346 int pkgFlags = 0;
8347 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008348 PackageSetting ps = new PackageSetting(name, realName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008349 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008350 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008351 String timeStampStr = parser.getAttributeValue(null, "ts");
8352 if (timeStampStr != null) {
8353 try {
8354 long timeStamp = Long.parseLong(timeStampStr);
8355 ps.setTimeStamp(timeStamp, timeStampStr);
8356 } catch (NumberFormatException e) {
8357 }
8358 }
8359 String idStr = parser.getAttributeValue(null, "userId");
8360 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
8361 if(ps.userId <= 0) {
8362 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8363 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
8364 }
8365 int outerDepth = parser.getDepth();
8366 int type;
8367 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8368 && (type != XmlPullParser.END_TAG
8369 || parser.getDepth() > outerDepth)) {
8370 if (type == XmlPullParser.END_TAG
8371 || type == XmlPullParser.TEXT) {
8372 continue;
8373 }
8374
8375 String tagName = parser.getName();
8376 if (tagName.equals("perms")) {
8377 readGrantedPermissionsLP(parser,
8378 ps.grantedPermissions);
8379 } else {
8380 reportSettingsProblem(Log.WARN,
8381 "Unknown element under <updated-package>: "
8382 + parser.getName());
8383 XmlUtils.skipCurrentTag(parser);
8384 }
8385 }
8386 mDisabledSysPackages.put(name, ps);
8387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 private void readPackageLP(XmlPullParser parser)
8390 throws XmlPullParserException, IOException {
8391 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008392 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 String idStr = null;
8394 String sharedIdStr = null;
8395 String codePathStr = null;
8396 String resourcePathStr = null;
8397 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02008398 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008399 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008400 int pkgFlags = 0;
8401 String timeStampStr;
8402 long timeStamp = 0;
8403 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008404 String version = null;
8405 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 try {
8407 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008408 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008410 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008411 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8412 codePathStr = parser.getAttributeValue(null, "codePath");
8413 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008414 version = parser.getAttributeValue(null, "version");
8415 if (version != null) {
8416 try {
8417 versionCode = Integer.parseInt(version);
8418 } catch (NumberFormatException e) {
8419 }
8420 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008421 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008422
8423 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008424 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008425 try {
8426 pkgFlags = Integer.parseInt(systemStr);
8427 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 }
8429 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008430 // For backward compatibility
8431 systemStr = parser.getAttributeValue(null, "system");
8432 if (systemStr != null) {
8433 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
8434 } else {
8435 // Old settings that don't specify system... just treat
8436 // them as system, good enough.
8437 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 }
8440 timeStampStr = parser.getAttributeValue(null, "ts");
8441 if (timeStampStr != null) {
8442 try {
8443 timeStamp = Long.parseLong(timeStampStr);
8444 } catch (NumberFormatException e) {
8445 }
8446 }
8447 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
8448 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
8449 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8450 if (resourcePathStr == null) {
8451 resourcePathStr = codePathStr;
8452 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008453 if (realName != null) {
8454 realName = realName.intern();
8455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008456 if (name == null) {
8457 reportSettingsProblem(Log.WARN,
8458 "Error in package manager settings: <package> has no name at "
8459 + parser.getPositionDescription());
8460 } else if (codePathStr == null) {
8461 reportSettingsProblem(Log.WARN,
8462 "Error in package manager settings: <package> has no codePath at "
8463 + parser.getPositionDescription());
8464 } else if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008465 packageSetting = addPackageLP(name.intern(), realName,
8466 new File(codePathStr), new File(resourcePathStr),
8467 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8469 + ": userId=" + userId + " pkg=" + packageSetting);
8470 if (packageSetting == null) {
8471 reportSettingsProblem(Log.ERROR,
8472 "Failure adding uid " + userId
8473 + " while parsing settings at "
8474 + parser.getPositionDescription());
8475 } else {
8476 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8477 }
8478 } else if (sharedIdStr != null) {
8479 userId = sharedIdStr != null
8480 ? Integer.parseInt(sharedIdStr) : 0;
8481 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008482 packageSetting = new PendingPackage(name.intern(), realName,
8483 new File(codePathStr), new File(resourcePathStr),
8484 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008485 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8486 mPendingPackages.add((PendingPackage) packageSetting);
8487 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8488 + ": sharedUserId=" + userId + " pkg="
8489 + packageSetting);
8490 } else {
8491 reportSettingsProblem(Log.WARN,
8492 "Error in package manager settings: package "
8493 + name + " has bad sharedId " + sharedIdStr
8494 + " at " + parser.getPositionDescription());
8495 }
8496 } else {
8497 reportSettingsProblem(Log.WARN,
8498 "Error in package manager settings: package "
8499 + name + " has bad userId " + idStr + " at "
8500 + parser.getPositionDescription());
8501 }
8502 } catch (NumberFormatException e) {
8503 reportSettingsProblem(Log.WARN,
8504 "Error in package manager settings: package "
8505 + name + " has bad userId " + idStr + " at "
8506 + parser.getPositionDescription());
8507 }
8508 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008509 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02008510 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008511 final String enabledStr = parser.getAttributeValue(null, "enabled");
8512 if (enabledStr != null) {
8513 if (enabledStr.equalsIgnoreCase("true")) {
8514 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
8515 } else if (enabledStr.equalsIgnoreCase("false")) {
8516 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
8517 } else if (enabledStr.equalsIgnoreCase("default")) {
8518 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8519 } else {
8520 reportSettingsProblem(Log.WARN,
8521 "Error in package manager settings: package "
8522 + name + " has bad enabled value: " + idStr
8523 + " at " + parser.getPositionDescription());
8524 }
8525 } else {
8526 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8527 }
8528 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
8529 if (installStatusStr != null) {
8530 if (installStatusStr.equalsIgnoreCase("false")) {
8531 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
8532 } else {
8533 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
8534 }
8535 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008537 int outerDepth = parser.getDepth();
8538 int type;
8539 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8540 && (type != XmlPullParser.END_TAG
8541 || parser.getDepth() > outerDepth)) {
8542 if (type == XmlPullParser.END_TAG
8543 || type == XmlPullParser.TEXT) {
8544 continue;
8545 }
8546
8547 String tagName = parser.getName();
8548 if (tagName.equals("disabled-components")) {
8549 readDisabledComponentsLP(packageSetting, parser);
8550 } else if (tagName.equals("enabled-components")) {
8551 readEnabledComponentsLP(packageSetting, parser);
8552 } else if (tagName.equals("sigs")) {
8553 packageSetting.signatures.readXml(parser, mPastSignatures);
8554 } else if (tagName.equals("perms")) {
8555 readGrantedPermissionsLP(parser,
8556 packageSetting.loadedPermissions);
8557 packageSetting.permissionsFixed = true;
8558 } else {
8559 reportSettingsProblem(Log.WARN,
8560 "Unknown element under <package>: "
8561 + parser.getName());
8562 XmlUtils.skipCurrentTag(parser);
8563 }
8564 }
8565 } else {
8566 XmlUtils.skipCurrentTag(parser);
8567 }
8568 }
8569
8570 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
8571 XmlPullParser parser)
8572 throws IOException, XmlPullParserException {
8573 int outerDepth = parser.getDepth();
8574 int type;
8575 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8576 && (type != XmlPullParser.END_TAG
8577 || parser.getDepth() > outerDepth)) {
8578 if (type == XmlPullParser.END_TAG
8579 || type == XmlPullParser.TEXT) {
8580 continue;
8581 }
8582
8583 String tagName = parser.getName();
8584 if (tagName.equals("item")) {
8585 String name = parser.getAttributeValue(null, "name");
8586 if (name != null) {
8587 packageSetting.disabledComponents.add(name.intern());
8588 } else {
8589 reportSettingsProblem(Log.WARN,
8590 "Error in package manager settings: <disabled-components> has"
8591 + " no name at " + parser.getPositionDescription());
8592 }
8593 } else {
8594 reportSettingsProblem(Log.WARN,
8595 "Unknown element under <disabled-components>: "
8596 + parser.getName());
8597 }
8598 XmlUtils.skipCurrentTag(parser);
8599 }
8600 }
8601
8602 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
8603 XmlPullParser parser)
8604 throws IOException, XmlPullParserException {
8605 int outerDepth = parser.getDepth();
8606 int type;
8607 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8608 && (type != XmlPullParser.END_TAG
8609 || parser.getDepth() > outerDepth)) {
8610 if (type == XmlPullParser.END_TAG
8611 || type == XmlPullParser.TEXT) {
8612 continue;
8613 }
8614
8615 String tagName = parser.getName();
8616 if (tagName.equals("item")) {
8617 String name = parser.getAttributeValue(null, "name");
8618 if (name != null) {
8619 packageSetting.enabledComponents.add(name.intern());
8620 } else {
8621 reportSettingsProblem(Log.WARN,
8622 "Error in package manager settings: <enabled-components> has"
8623 + " no name at " + parser.getPositionDescription());
8624 }
8625 } else {
8626 reportSettingsProblem(Log.WARN,
8627 "Unknown element under <enabled-components>: "
8628 + parser.getName());
8629 }
8630 XmlUtils.skipCurrentTag(parser);
8631 }
8632 }
8633
8634 private void readSharedUserLP(XmlPullParser parser)
8635 throws XmlPullParserException, IOException {
8636 String name = null;
8637 String idStr = null;
8638 int pkgFlags = 0;
8639 SharedUserSetting su = null;
8640 try {
8641 name = parser.getAttributeValue(null, "name");
8642 idStr = parser.getAttributeValue(null, "userId");
8643 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8644 if ("true".equals(parser.getAttributeValue(null, "system"))) {
8645 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8646 }
8647 if (name == null) {
8648 reportSettingsProblem(Log.WARN,
8649 "Error in package manager settings: <shared-user> has no name at "
8650 + parser.getPositionDescription());
8651 } else if (userId == 0) {
8652 reportSettingsProblem(Log.WARN,
8653 "Error in package manager settings: shared-user "
8654 + name + " has bad userId " + idStr + " at "
8655 + parser.getPositionDescription());
8656 } else {
8657 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
8658 reportSettingsProblem(Log.ERROR,
8659 "Occurred while parsing settings at "
8660 + parser.getPositionDescription());
8661 }
8662 }
8663 } catch (NumberFormatException e) {
8664 reportSettingsProblem(Log.WARN,
8665 "Error in package manager settings: package "
8666 + name + " has bad userId " + idStr + " at "
8667 + parser.getPositionDescription());
8668 };
8669
8670 if (su != null) {
8671 int outerDepth = parser.getDepth();
8672 int type;
8673 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8674 && (type != XmlPullParser.END_TAG
8675 || parser.getDepth() > outerDepth)) {
8676 if (type == XmlPullParser.END_TAG
8677 || type == XmlPullParser.TEXT) {
8678 continue;
8679 }
8680
8681 String tagName = parser.getName();
8682 if (tagName.equals("sigs")) {
8683 su.signatures.readXml(parser, mPastSignatures);
8684 } else if (tagName.equals("perms")) {
8685 readGrantedPermissionsLP(parser, su.loadedPermissions);
8686 } else {
8687 reportSettingsProblem(Log.WARN,
8688 "Unknown element under <shared-user>: "
8689 + parser.getName());
8690 XmlUtils.skipCurrentTag(parser);
8691 }
8692 }
8693
8694 } else {
8695 XmlUtils.skipCurrentTag(parser);
8696 }
8697 }
8698
8699 private void readGrantedPermissionsLP(XmlPullParser parser,
8700 HashSet<String> outPerms) throws IOException, XmlPullParserException {
8701 int outerDepth = parser.getDepth();
8702 int type;
8703 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8704 && (type != XmlPullParser.END_TAG
8705 || parser.getDepth() > outerDepth)) {
8706 if (type == XmlPullParser.END_TAG
8707 || type == XmlPullParser.TEXT) {
8708 continue;
8709 }
8710
8711 String tagName = parser.getName();
8712 if (tagName.equals("item")) {
8713 String name = parser.getAttributeValue(null, "name");
8714 if (name != null) {
8715 outPerms.add(name.intern());
8716 } else {
8717 reportSettingsProblem(Log.WARN,
8718 "Error in package manager settings: <perms> has"
8719 + " no name at " + parser.getPositionDescription());
8720 }
8721 } else {
8722 reportSettingsProblem(Log.WARN,
8723 "Unknown element under <perms>: "
8724 + parser.getName());
8725 }
8726 XmlUtils.skipCurrentTag(parser);
8727 }
8728 }
8729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 private void readPreferredActivitiesLP(XmlPullParser parser)
8731 throws XmlPullParserException, IOException {
8732 int outerDepth = parser.getDepth();
8733 int type;
8734 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8735 && (type != XmlPullParser.END_TAG
8736 || parser.getDepth() > outerDepth)) {
8737 if (type == XmlPullParser.END_TAG
8738 || type == XmlPullParser.TEXT) {
8739 continue;
8740 }
8741
8742 String tagName = parser.getName();
8743 if (tagName.equals("item")) {
8744 PreferredActivity pa = new PreferredActivity(parser);
8745 if (pa.mParseError == null) {
8746 mPreferredActivities.addFilter(pa);
8747 } else {
8748 reportSettingsProblem(Log.WARN,
8749 "Error in package manager settings: <preferred-activity> "
8750 + pa.mParseError + " at "
8751 + parser.getPositionDescription());
8752 }
8753 } else {
8754 reportSettingsProblem(Log.WARN,
8755 "Unknown element under <preferred-activities>: "
8756 + parser.getName());
8757 XmlUtils.skipCurrentTag(parser);
8758 }
8759 }
8760 }
8761
8762 // Returns -1 if we could not find an available UserId to assign
8763 private int newUserIdLP(Object obj) {
8764 // Let's be stupidly inefficient for now...
8765 final int N = mUserIds.size();
8766 for (int i=0; i<N; i++) {
8767 if (mUserIds.get(i) == null) {
8768 mUserIds.set(i, obj);
8769 return FIRST_APPLICATION_UID + i;
8770 }
8771 }
8772
8773 // None left?
8774 if (N >= MAX_APPLICATION_UIDS) {
8775 return -1;
8776 }
8777
8778 mUserIds.add(obj);
8779 return FIRST_APPLICATION_UID + N;
8780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782 public PackageSetting getDisabledSystemPkg(String name) {
8783 synchronized(mPackages) {
8784 PackageSetting ps = mDisabledSysPackages.get(name);
8785 return ps;
8786 }
8787 }
8788
8789 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
8790 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
8791 if (Config.LOGV) {
8792 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
8793 + " componentName = " + componentInfo.name);
8794 Log.v(TAG, "enabledComponents: "
8795 + Arrays.toString(packageSettings.enabledComponents.toArray()));
8796 Log.v(TAG, "disabledComponents: "
8797 + Arrays.toString(packageSettings.disabledComponents.toArray()));
8798 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008799 if (packageSettings == null) {
8800 if (false) {
8801 Log.w(TAG, "WAITING FOR DEBUGGER");
8802 Debug.waitForDebugger();
8803 Log.i(TAG, "We will crash!");
8804 }
8805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008806 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
8807 || ((componentInfo.enabled
8808 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
8809 || (componentInfo.applicationInfo.enabled
8810 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
8811 && !packageSettings.disabledComponents.contains(componentInfo.name))
8812 || packageSettings.enabledComponents.contains(componentInfo.name));
8813 }
8814 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008815
8816 // ------- apps on sdcard specific code -------
8817 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08008818 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08008819 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008820 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008821 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008822
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008823 private String getEncryptKey() {
8824 try {
8825 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8826 if (sdEncKey == null) {
8827 sdEncKey = SystemKeyStore.getInstance().
8828 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
8829 if (sdEncKey == null) {
8830 Log.e(TAG, "Failed to create encryption keys");
8831 return null;
8832 }
8833 }
8834 return sdEncKey;
8835 } catch (NoSuchAlgorithmException nsae) {
8836 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
8837 return null;
8838 }
8839 }
8840
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008841 static String getTempContainerId() {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008842 String prefix = "smdl2tmp";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008843 int tmpIdx = 1;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008844 String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008845 if (list != null) {
8846 int idx = 0;
8847 int idList[] = new int[MAX_CONTAINERS];
8848 boolean neverFound = true;
8849 for (String name : list) {
8850 // Ignore null entries
8851 if (name == null) {
8852 continue;
8853 }
8854 int sidx = name.indexOf(prefix);
8855 if (sidx == -1) {
8856 // Not a temp file. just ignore
8857 continue;
8858 }
8859 String subStr = name.substring(sidx + prefix.length());
8860 idList[idx] = -1;
8861 if (subStr != null) {
8862 try {
8863 int cid = Integer.parseInt(subStr);
8864 idList[idx++] = cid;
8865 neverFound = false;
8866 } catch (NumberFormatException e) {
8867 }
8868 }
8869 }
8870 if (!neverFound) {
8871 // Sort idList
8872 Arrays.sort(idList);
8873 for (int j = 1; j <= idList.length; j++) {
8874 if (idList[j-1] != j) {
8875 tmpIdx = j;
8876 break;
8877 }
8878 }
8879 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008880 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008881 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008882 }
8883
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08008884 /*
8885 * Return true if PackageManager does have packages to be updated.
8886 */
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008887 public boolean updateExternalMediaStatus(final boolean mediaStatus) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008888 synchronized (mPackages) {
8889 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
8890 mediaStatus+", mMediaMounted=" + mMediaMounted);
8891 if (mediaStatus == mMediaMounted) {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008892 return false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008893 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008894 mMediaMounted = mediaStatus;
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08008895 boolean ret = false;
8896 synchronized (mPackages) {
8897 Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
8898 ret = appList != null && appList.size() > 0;
8899 }
8900 if (!ret) {
8901 // No packages will be effected by the sdcard update. Just return.
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008902 return false;
8903 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008904 // Queue up an async operation since the package installation may take a little while.
8905 mHandler.post(new Runnable() {
8906 public void run() {
8907 mHandler.removeCallbacks(this);
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08008908 // If we are up here that means there are packages to be
8909 // enabled or disabled.
8910 final HashMap<SdInstallArgs, String> processCids =
8911 new HashMap<SdInstallArgs, String>();
8912 final int[] uidArr = getExternalMediaPackages(mediaStatus, processCids);
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008913 if (mediaStatus) {
8914 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
8915 loadMediaPackages(processCids, uidArr);
8916 startCleaningPackages();
8917 } else {
8918 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
8919 unloadMediaPackages(processCids, uidArr);
8920 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008921 }
8922 });
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008923 return true;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008924 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008925 }
8926
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008927 private int[] getExternalMediaPackages(boolean mediaStatus,
8928 Map<SdInstallArgs, String> processCids) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008929 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008930 if (list == null || list.length == 0) {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008931 return null;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008932 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008933
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008934 int uidList[] = new int[list.length];
8935 int num = 0;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008936 synchronized (mPackages) {
8937 Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
8938 for (String cid : list) {
8939 SdInstallArgs args = new SdInstallArgs(cid);
8940 String removeEntry = null;
8941 for (String app : appList) {
8942 if (args.matchContainer(app)) {
8943 removeEntry = app;
8944 break;
8945 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008946 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008947 if (removeEntry == null) {
8948 // No matching app on device. Skip entry or may be cleanup?
8949 // Ignore default package
8950 continue;
8951 }
8952 appList.remove(removeEntry);
8953 PackageSetting ps = mSettings.mPackages.get(removeEntry);
8954 processCids.put(args, ps.codePathString);
8955 int uid = ps.userId;
8956 if (uid != -1) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008957 uidList[num++] = uid;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008958 }
8959 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008960 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008961 int uidArr[] = null;
8962 if (num > 0) {
8963 // Sort uid list
8964 Arrays.sort(uidList, 0, num);
8965 // Throw away duplicates
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008966 uidArr = new int[num];
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008967 uidArr[0] = uidList[0];
8968 int di = 0;
8969 for (int i = 1; i < num; i++) {
8970 if (uidList[i-1] != uidList[i]) {
8971 uidArr[di++] = uidList[i];
8972 }
8973 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008974 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008975 return uidArr;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008976 }
8977
8978 private void sendResourcesChangedBroadcast(boolean mediaStatus,
8979 ArrayList<String> pkgList, int uidArr[]) {
8980 int size = pkgList.size();
8981 if (size > 0) {
8982 // Send broadcasts here
8983 Bundle extras = new Bundle();
8984 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
8985 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008986 if (uidArr != null) {
8987 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
8988 }
8989 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
8990 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008991 sendPackageBroadcast(action, null, extras);
8992 }
8993 }
8994
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008995 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008996 ArrayList<String> pkgList = new ArrayList<String>();
8997 Set<SdInstallArgs> keys = processCids.keySet();
8998 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008999 String codePath = processCids.get(args);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009000 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install pkg : "
9001 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009002 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009003 Log.e(TAG, "Failed to install package: " + codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009004 continue;
9005 }
9006 // Parse package
9007 int parseFlags = PackageParser.PARSE_CHATTY |
9008 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
9009 PackageParser pp = new PackageParser(codePath);
9010 pp.setSeparateProcesses(mSeparateProcesses);
9011 final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
9012 codePath, mMetrics, parseFlags);
9013 if (pkg == null) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009014 Log.e(TAG, "Trying to install pkg : "
9015 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009016 continue;
9017 }
9018 setApplicationInfoPaths(pkg, codePath, codePath);
9019 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
9020 synchronized (mInstallLock) {
9021 // Scan the package
9022 if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
9023 synchronized (mPackages) {
9024 // Grant permissions
9025 grantPermissionsLP(pkg, false);
9026 // Persist settings
9027 mSettings.writeLP();
9028 retCode = PackageManager.INSTALL_SUCCEEDED;
9029 pkgList.add(pkg.packageName);
9030 }
9031 } else {
9032 Log.i(TAG, "Failed to install package: " + pkg.packageName + " from sdcard");
9033 }
9034 }
9035 args.doPostInstall(retCode);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009036 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009037 // Send a broadcast to let everyone know we are done processing
9038 sendResourcesChangedBroadcast(true, pkgList, uidArr);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009039 if (pkgList.size() > 0) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009040 Runtime.getRuntime().gc();
9041 // If something failed do we clean up here or next install?
9042 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009043 }
9044
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009045 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009046 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009047 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009048 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009049 Set<SdInstallArgs> keys = processCids.keySet();
9050 for (SdInstallArgs args : keys) {
9051 String cid = args.cid;
9052 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009053 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009054 // Delete package internally
9055 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9056 synchronized (mInstallLock) {
9057 boolean res = deletePackageLI(pkgName, false,
9058 PackageManager.DONT_DELETE_DATA, outInfo);
9059 if (res) {
9060 pkgList.add(pkgName);
9061 } else {
9062 Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009063 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009064 }
9065 }
9066 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009067 sendResourcesChangedBroadcast(false, pkgList, uidArr);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009068 // Send broadcasts
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009069 if (pkgList.size() > 0) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009070 Runtime.getRuntime().gc();
9071 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009072 // Do clean up. Just unmount
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009073 for (SdInstallArgs args : failedList) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009074 synchronized (mInstallLock) {
9075 args.doPostDeleteLI(false);
9076 }
9077 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009078 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009079
9080 public void movePackage(final String packageName,
9081 final IPackageMoveObserver observer, final int flags) {
9082 if (packageName == null) {
9083 return;
9084 }
9085 mContext.enforceCallingOrSelfPermission(
9086 android.Manifest.permission.MOVE_PACKAGE, null);
9087 int returnCode = PackageManager.MOVE_SUCCEEDED;
9088 int currFlags = 0;
9089 int newFlags = 0;
9090 synchronized (mPackages) {
9091 PackageParser.Package pkg = mPackages.get(packageName);
9092 if (pkg == null) {
9093 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9094 }
9095 // Disable moving fwd locked apps and system packages
9096 if (pkg.applicationInfo != null &&
9097 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
9098 Log.w(TAG, "Cannot move system application");
9099 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
9100 } else if (pkg.applicationInfo != null &&
9101 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
9102 Log.w(TAG, "Cannot move forward locked app.");
9103 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
9104 } else {
9105 // Find install location first
9106 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
9107 (flags & PackageManager.MOVE_INTERNAL) != 0) {
9108 Log.w(TAG, "Ambigous flags specified for move location.");
9109 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9110 } else {
9111 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
9112 PackageManager.INSTALL_EXTERNAL : 0;
9113 currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0 ?
9114 PackageManager.INSTALL_EXTERNAL : 0;
9115 if (newFlags == currFlags) {
9116 Log.w(TAG, "No move required. Trying to move to same location");
9117 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9118 }
9119 }
9120 }
9121 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
9122 processPendingMove(new MoveParams(null, observer, 0, null), returnCode);
9123 } else {
9124 Message msg = mHandler.obtainMessage(INIT_COPY);
9125 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
9126 pkg.applicationInfo.publicSourceDir);
9127 MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
9128 packageName);
9129 msg.obj = mp;
9130 mHandler.sendMessage(msg);
9131 }
9132 }
9133 }
9134
9135 private void processPendingMove(final MoveParams mp, final int currentStatus) {
9136 // Queue up an async operation since the package deletion may take a little while.
9137 mHandler.post(new Runnable() {
9138 public void run() {
9139 mHandler.removeCallbacks(this);
9140 int returnCode = currentStatus;
9141 boolean moveSucceeded = (returnCode == PackageManager.MOVE_SUCCEEDED);
9142 if (moveSucceeded) {
9143 int uid = -1;
9144 synchronized (mPackages) {
9145 uid = mPackages.get(mp.packageName).applicationInfo.uid;
9146 }
9147 ArrayList<String> pkgList = new ArrayList<String>();
9148 pkgList.add(mp.packageName);
9149 int uidArr[] = new int[] { uid };
9150 // Send resources unavailable broadcast
9151 sendResourcesChangedBroadcast(false, pkgList, uidArr);
9152
9153 // Update package code and resource paths
9154 synchronized (mPackages) {
9155 PackageParser.Package pkg = mPackages.get(mp.packageName);
9156 if (pkg != null) {
9157 String oldCodePath = pkg.mPath;
9158 String newCodePath = mp.targetArgs.getCodePath();
9159 String newResPath = mp.targetArgs.getResourcePath();
9160 pkg.mPath = newCodePath;
9161 // Move dex files around
9162 if (moveDexFiles(pkg)
9163 != PackageManager.INSTALL_SUCCEEDED) {
9164 // Moving of dex files failed. Set
9165 // error code and abort move.
9166 pkg.mPath = pkg.mScanPath;
9167 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9168 moveSucceeded = false;
9169 } else {
9170 pkg.mScanPath = newCodePath;
9171 pkg.applicationInfo.sourceDir = newCodePath;
9172 pkg.applicationInfo.publicSourceDir = newResPath;
9173 PackageSetting ps = (PackageSetting) pkg.mExtras;
9174 ps.codePath = new File(pkg.applicationInfo.sourceDir);
9175 ps.codePathString = ps.codePath.getPath();
9176 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
9177 ps.resourcePathString = ps.resourcePath.getPath();
9178 // Set the application info flag correctly.
9179 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
9180 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_ON_SDCARD;
9181 } else {
9182 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_ON_SDCARD;
9183 }
9184 ps.setFlags(pkg.applicationInfo.flags);
9185 mAppDirs.remove(oldCodePath);
9186 mAppDirs.put(newCodePath, pkg);
9187 // Persist settings
9188 mSettings.writeLP();
9189 }
9190 }
9191 }
9192 if (moveSucceeded) {
9193 // Delete older code
9194 synchronized (mInstallLock) {
9195 mp.srcArgs.cleanUpResourcesLI();
9196 }
9197 // Send resources available broadcast
9198 sendResourcesChangedBroadcast(true, pkgList, uidArr);
9199 Runtime.getRuntime().gc();
9200 }
9201 }
9202 if (!moveSucceeded){
9203 // Clean up failed installation
9204 if (mp.targetArgs != null) {
9205 mp.targetArgs.doPostInstall(
9206 PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
9207 }
9208 }
9209 IPackageMoveObserver observer = mp.observer;
9210 if (observer != null) {
9211 try {
9212 observer.packageMoved(mp.packageName, returnCode);
9213 } catch (RemoteException e) {
9214 Log.i(TAG, "Observer no longer exists.");
9215 }
9216 }
9217 }
9218 });
9219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220}