blob: 1ff0244a98bdbae2c67f6ee67069f0f09d8ae15b [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;
31import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080032import android.app.admin.DevicePolicyManager;
33import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080034import android.app.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 Amalapurapu9b10ef52010-03-03 09:45:24 -0800321 // Service Connection to remote media container service to copy
322 // package uri's from external media onto secure containers
323 // or internal storage.
324 private IMediaContainerService mContainerService = null;
325
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700326 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800327 static final int MCS_BOUND = 3;
328 static final int END_COPY = 4;
329 static final int INIT_COPY = 5;
330 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800331 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800332 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800333 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800334 static final int MCS_RECONNECT = 10;
335 static final int MCS_GIVE_UP = 11;
336
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700337 // Delay time in millisecs
338 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800339 final private DefaultContainerConnection mDefContainerConn =
340 new DefaultContainerConnection();
341 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800342 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800343 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800344 IMediaContainerService imcs =
345 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800346 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800347 }
348
349 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800350 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800351 }
352 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700353
Christopher Tate1bb69062010-02-19 17:02:12 -0800354 // Recordkeeping of restore-after-install operations that are currently in flight
355 // between the Package Manager and the Backup Manager
356 class PostInstallData {
357 public InstallArgs args;
358 public PackageInstalledInfo res;
359
360 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
361 args = _a;
362 res = _r;
363 }
364 };
365 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
366 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
367
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700368 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800369 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800370 final ArrayList<HandlerParams> mPendingInstalls =
371 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800372
373 private boolean connectToService() {
374 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
375 " DefaultContainerService");
376 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
377 if (mContext.bindService(service, mDefContainerConn,
378 Context.BIND_AUTO_CREATE)) {
379 mBound = true;
380 return true;
381 }
382 return false;
383 }
384
385 private void disconnectService() {
386 mContainerService = null;
387 mBound = false;
388 mContext.unbindService(mDefContainerConn);
389 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800390
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700391 PackageHandler(Looper looper) {
392 super(looper);
393 }
394 public void handleMessage(Message msg) {
395 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800396 case INIT_COPY: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800397 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800398 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800399 int idx = mPendingInstalls.size();
400 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
401 // If a bind was already initiated we dont really
402 // need to do anything. The pending install
403 // will be processed later on.
404 if (!mBound) {
405 // If this is the only one pending we might
406 // have to bind to the service again.
407 if (!connectToService()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800408 Log.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800409 params.serviceError();
410 return;
411 } else {
412 // Once we bind to the service, the first
413 // pending request will be processed.
414 mPendingInstalls.add(idx, params);
415 }
416 } else {
417 mPendingInstalls.add(idx, params);
418 // Already bound to the service. Just make
419 // sure we trigger off processing the first request.
420 if (idx == 0) {
421 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800422 }
423 }
424 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800425 }
426 case MCS_BOUND: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800427 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800428 if (msg.obj != null) {
429 mContainerService = (IMediaContainerService) msg.obj;
430 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800431 if (mContainerService == null) {
432 // Something seriously wrong. Bail out
433 Log.e(TAG, "Cannot bind to media container service");
434 for (HandlerParams params : mPendingInstalls) {
435 mPendingInstalls.remove(0);
436 // Indicate service bind error
437 params.serviceError();
438 }
439 mPendingInstalls.clear();
440 } else if (mPendingInstalls.size() > 0) {
441 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800442 if (params != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800443 params.startCopy();
444 }
445 } else {
446 // Should never happen ideally.
447 Log.w(TAG, "Empty queue");
448 }
449 break;
450 }
451 case MCS_RECONNECT : {
452 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
453 if (mPendingInstalls.size() > 0) {
454 if (mBound) {
455 disconnectService();
456 }
457 if (!connectToService()) {
458 Log.e(TAG, "Failed to bind to media container service");
459 for (HandlerParams params : mPendingInstalls) {
460 mPendingInstalls.remove(0);
461 // Indicate service bind error
462 params.serviceError();
463 }
464 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800465 }
466 }
467 break;
468 }
469 case MCS_UNBIND : {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800470 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
471 // Delete pending install
472 if (mPendingInstalls.size() > 0) {
473 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800474 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800475 if (mPendingInstalls.size() == 0) {
476 if (mBound) {
477 disconnectService();
478 }
479 } else {
480 // There are more pending requests in queue.
481 // Just post MCS_BOUND message to trigger processing
482 // of next pending install.
483 mHandler.sendEmptyMessage(MCS_BOUND);
484 }
485 break;
486 }
487 case MCS_GIVE_UP: {
488 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
489 HandlerParams params = mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800490 break;
491 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700492 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800493 String packages[];
494 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700495 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700496 int uids[];
497 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800498 if (mPendingBroadcasts == null) {
499 return;
500 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700501 size = mPendingBroadcasts.size();
502 if (size <= 0) {
503 // Nothing to be done. Just return
504 return;
505 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800506 packages = new String[size];
507 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700508 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800509 Iterator<HashMap.Entry<String, ArrayList<String>>>
510 it = mPendingBroadcasts.entrySet().iterator();
511 int i = 0;
512 while (it.hasNext() && i < size) {
513 HashMap.Entry<String, ArrayList<String>> ent = it.next();
514 packages[i] = ent.getKey();
515 components[i] = ent.getValue();
516 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700517 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800518 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700519 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800520 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700521 mPendingBroadcasts.clear();
522 }
523 // Send broadcasts
524 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800525 sendPackageChangedBroadcast(packages[i], true,
526 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700527 }
528 break;
529 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800530 case START_CLEANING_PACKAGE: {
531 String packageName = (String)msg.obj;
532 synchronized (mPackages) {
533 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
534 mSettings.mPackagesToBeCleaned.add(packageName);
535 }
536 }
537 startCleaningPackages();
538 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800539 case POST_INSTALL: {
540 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
541 PostInstallData data = mRunningInstalls.get(msg.arg1);
542 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800543 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800544
545 if (data != null) {
546 InstallArgs args = data.args;
547 PackageInstalledInfo res = data.res;
548
549 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
550 res.removedInfo.sendBroadcast(false, true);
551 Bundle extras = new Bundle(1);
552 extras.putInt(Intent.EXTRA_UID, res.uid);
553 final boolean update = res.removedInfo.removedPackage != null;
554 if (update) {
555 extras.putBoolean(Intent.EXTRA_REPLACING, true);
556 }
557 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
558 res.pkg.applicationInfo.packageName,
559 extras);
560 if (update) {
561 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
562 res.pkg.applicationInfo.packageName,
563 extras);
564 }
565 if (res.removedInfo.args != null) {
566 // Remove the replaced package's older resources safely now
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800567 deleteOld = true;
Christopher Tate1bb69062010-02-19 17:02:12 -0800568 }
569 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800570 // Force a gc to clear up things
Christopher Tate1bb69062010-02-19 17:02:12 -0800571 Runtime.getRuntime().gc();
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800572 // We delete after a gc for applications on sdcard.
573 if (deleteOld) {
574 synchronized (mInstallLock) {
575 res.removedInfo.args.doPostDeleteLI(true);
576 }
577 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800578 if (args.observer != null) {
579 try {
580 args.observer.packageInstalled(res.name, res.returnCode);
581 } catch (RemoteException e) {
582 Log.i(TAG, "Observer no longer exists.");
583 }
584 }
585 } else {
586 Log.e(TAG, "Bogus post-install token " + msg.arg1);
587 }
588 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700589 }
590 }
591 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800592
593 static boolean installOnSd(int flags) {
594 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800595 ((flags & PackageManager.INSTALL_EXTERNAL) == 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800596 return false;
597 }
598 return true;
599 }
600
601 static boolean isFwdLocked(int flags) {
602 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
603 return true;
604 }
605 return false;
606 }
607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 public static final IPackageManager main(Context context, boolean factoryTest) {
609 PackageManagerService m = new PackageManagerService(context, factoryTest);
610 ServiceManager.addService("package", m);
611 return m;
612 }
613
614 static String[] splitString(String str, char sep) {
615 int count = 1;
616 int i = 0;
617 while ((i=str.indexOf(sep, i)) >= 0) {
618 count++;
619 i++;
620 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 String[] res = new String[count];
623 i=0;
624 count = 0;
625 int lastI=0;
626 while ((i=str.indexOf(sep, i)) >= 0) {
627 res[count] = str.substring(lastI, i);
628 count++;
629 i++;
630 lastI = i;
631 }
632 res[count] = str.substring(lastI, str.length());
633 return res;
634 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800637 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 if (mSdkVersion <= 0) {
641 Log.w(TAG, "**** ro.build.version.sdk not set!");
642 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 mContext = context;
645 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700646 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 mMetrics = new DisplayMetrics();
648 mSettings = new Settings();
649 mSettings.addSharedUserLP("android.uid.system",
650 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
651 mSettings.addSharedUserLP("android.uid.phone",
652 MULTIPLE_APPLICATION_UIDS
653 ? RADIO_UID : FIRST_APPLICATION_UID,
654 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400655 mSettings.addSharedUserLP("android.uid.log",
656 MULTIPLE_APPLICATION_UIDS
657 ? LOG_UID : FIRST_APPLICATION_UID,
658 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659
660 String separateProcesses = SystemProperties.get("debug.separate_processes");
661 if (separateProcesses != null && separateProcesses.length() > 0) {
662 if ("*".equals(separateProcesses)) {
663 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
664 mSeparateProcesses = null;
665 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
666 } else {
667 mDefParseFlags = 0;
668 mSeparateProcesses = separateProcesses.split(",");
669 Log.w(TAG, "Running with debug.separate_processes: "
670 + separateProcesses);
671 }
672 } else {
673 mDefParseFlags = 0;
674 mSeparateProcesses = null;
675 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677 Installer installer = new Installer();
678 // Little hacky thing to check if installd is here, to determine
679 // whether we are running on the simulator and thus need to take
680 // care of building the /data file structure ourself.
681 // (apparently the sim now has a working installer)
682 if (installer.ping() && Process.supportsProcesses()) {
683 mInstaller = installer;
684 } else {
685 mInstaller = null;
686 }
687
688 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
689 Display d = wm.getDefaultDisplay();
690 d.getMetrics(mMetrics);
691
692 synchronized (mInstallLock) {
693 synchronized (mPackages) {
694 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700695 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 File dataDir = Environment.getDataDirectory();
698 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800699 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
701
702 if (mInstaller == null) {
703 // Make sure these dirs exist, when we are running in
704 // the simulator.
705 // Make a wide-open directory for random misc stuff.
706 File miscDir = new File(dataDir, "misc");
707 miscDir.mkdirs();
708 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800709 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 mDrmAppPrivateInstallDir.mkdirs();
711 }
712
713 readPermissions();
714
715 mRestoredSettings = mSettings.readLP();
716 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800717
718 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800720
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800721 // Set flag to monitor and not change apk file paths when
722 // scanning install directories.
723 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700724 if (mNoDexOpt) {
725 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800726 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700727 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700732 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700735 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 /**
738 * Out of paranoia, ensure that everything in the boot class
739 * path has been dexed.
740 */
741 String bootClassPath = System.getProperty("java.boot.class.path");
742 if (bootClassPath != null) {
743 String[] paths = splitString(bootClassPath, ':');
744 for (int i=0; i<paths.length; i++) {
745 try {
746 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
747 libFiles.add(paths[i]);
748 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700749 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 }
751 } catch (FileNotFoundException e) {
752 Log.w(TAG, "Boot class path not found: " + paths[i]);
753 } catch (IOException e) {
754 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
755 }
756 }
757 } else {
758 Log.w(TAG, "No BOOTCLASSPATH found!");
759 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 /**
762 * Also ensure all external libraries have had dexopt run on them.
763 */
764 if (mSharedLibraries.size() > 0) {
765 Iterator<String> libs = mSharedLibraries.values().iterator();
766 while (libs.hasNext()) {
767 String lib = libs.next();
768 try {
769 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
770 libFiles.add(lib);
771 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700772 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 }
774 } catch (FileNotFoundException e) {
775 Log.w(TAG, "Library not found: " + lib);
776 } catch (IOException e) {
777 Log.w(TAG, "Exception reading library: " + lib, e);
778 }
779 }
780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 // Gross hack for now: we know this file doesn't contain any
783 // code, so don't dexopt it to avoid the resulting log spew.
784 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 /**
787 * And there are a number of commands implemented in Java, which
788 * we currently need to do the dexopt on so that they can be
789 * run from a non-root shell.
790 */
791 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700792 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 for (int i=0; i<frameworkFiles.length; i++) {
794 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
795 String path = libPath.getPath();
796 // Skip the file if we alrady did it.
797 if (libFiles.contains(path)) {
798 continue;
799 }
800 // Skip the file if it is not a type we want to dexopt.
801 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
802 continue;
803 }
804 try {
805 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
806 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700807 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 }
809 } catch (FileNotFoundException e) {
810 Log.w(TAG, "Jar not found: " + path);
811 } catch (IOException e) {
812 Log.w(TAG, "Exception reading jar: " + path, e);
813 }
814 }
815 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800816
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700817 if (didDexOpt) {
818 // If we had to do a dexopt of one of the previous
819 // things, then something on the system has changed.
820 // Consider this significant, and wipe away all other
821 // existing dexopt files to ensure we don't leave any
822 // dangling around.
823 String[] files = mDalvikCacheDir.list();
824 if (files != null) {
825 for (int i=0; i<files.length; i++) {
826 String fn = files[i];
827 if (fn.startsWith("data@app@")
828 || fn.startsWith("data@app-private@")) {
829 Log.i(TAG, "Pruning dalvik file: " + fn);
830 (new File(mDalvikCacheDir, fn)).delete();
831 }
832 }
833 }
834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800836
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800837 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 mFrameworkInstallObserver = new AppDirObserver(
839 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
840 mFrameworkInstallObserver.startWatching();
841 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800842 scanMode | SCAN_NO_DEX);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800843
844 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
846 mSystemInstallObserver = new AppDirObserver(
847 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
848 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800849 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800850
851 if (mInstaller != null) {
852 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
853 mInstaller.moveFiles();
854 }
855
856 // Prune any system packages that no longer exist.
857 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
858 while (psit.hasNext()) {
859 PackageSetting ps = psit.next();
860 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800861 && !mPackages.containsKey(ps.name)
862 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800863 psit.remove();
864 String msg = "System package " + ps.name
865 + " no longer exists; wiping its data";
866 reportSettingsProblem(Log.WARN, msg);
867 if (mInstaller != null) {
868 // XXX how to set useEncryptedFSDir for packages that
869 // are not encrypted?
870 mInstaller.remove(ps.name, true);
871 }
872 }
873 }
874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 mAppInstallDir = new File(dataDir, "app");
876 if (mInstaller == null) {
877 // Make sure these dirs exist, when we are running in
878 // the simulator.
879 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
880 }
881 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800882 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 //clean up list
884 for(int i = 0; i < deletePkgsList.size(); i++) {
885 //clean up here
886 cleanupInstallFailedPackage(deletePkgsList.get(i));
887 }
888 //delete tmp files
889 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800890
891 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 SystemClock.uptimeMillis());
893 mAppInstallObserver = new AppDirObserver(
894 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
895 mAppInstallObserver.startWatching();
896 scanDirLI(mAppInstallDir, 0, scanMode);
897
898 mDrmAppInstallObserver = new AppDirObserver(
899 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
900 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800901 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800903 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 SystemClock.uptimeMillis());
905 Log.i(TAG, "Time to scan packages: "
906 + ((SystemClock.uptimeMillis()-startTime)/1000f)
907 + " seconds");
908
909 updatePermissionsLP();
910
911 mSettings.writeLP();
912
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800913 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 // Now after opening every single application zip, make sure they
917 // are all flushed. Not really needed, but keeps things nice and
918 // tidy.
919 Runtime.getRuntime().gc();
920 } // synchronized (mPackages)
921 } // synchronized (mInstallLock)
922 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 @Override
925 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
926 throws RemoteException {
927 try {
928 return super.onTransact(code, data, reply, flags);
929 } catch (RuntimeException e) {
930 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
931 Log.e(TAG, "Package Manager Crash", e);
932 }
933 throw e;
934 }
935 }
936
Dianne Hackborne6620b22010-01-22 14:46:21 -0800937 void cleanupInstallFailedPackage(PackageSetting ps) {
938 Log.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 if (mInstaller != null) {
Kenny Rootbdbc9252010-01-28 12:03:49 -0800940 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
941 int retCode = mInstaller.remove(ps.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 if (retCode < 0) {
943 Log.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800944 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 }
946 } else {
947 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800948 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 File dataDir = new File(pkg.applicationInfo.dataDir);
950 dataDir.delete();
951 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800952 if (ps.codePath != null) {
953 if (!ps.codePath.delete()) {
954 Log.w(TAG, "Unable to remove old code file: " + ps.codePath);
955 }
956 }
957 if (ps.resourcePath != null) {
958 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
959 Log.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
960 }
961 }
962 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 }
964
965 void readPermissions() {
966 // Read permissions from .../etc/permission directory.
967 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
968 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
969 Log.w(TAG, "No directory " + libraryDir + ", skipping");
970 return;
971 }
972 if (!libraryDir.canRead()) {
973 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
974 return;
975 }
976
977 // Iterate over the files in the directory and scan .xml files
978 for (File f : libraryDir.listFiles()) {
979 // We'll read platform.xml last
980 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
981 continue;
982 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 if (!f.getPath().endsWith(".xml")) {
985 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
986 continue;
987 }
988 if (!f.canRead()) {
989 Log.w(TAG, "Permissions library file " + f + " cannot be read");
990 continue;
991 }
992
993 readPermissionsFromXml(f);
994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
997 final File permFile = new File(Environment.getRootDirectory(),
998 "etc/permissions/platform.xml");
999 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001000
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001001 StringBuilder sb = new StringBuilder(128);
1002 sb.append("Libs:");
1003 Iterator<String> it = mSharedLibraries.keySet().iterator();
1004 while (it.hasNext()) {
1005 sb.append(' ');
1006 String name = it.next();
1007 sb.append(name);
1008 sb.append(':');
1009 sb.append(mSharedLibraries.get(name));
1010 }
1011 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001012
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001013 sb.setLength(0);
1014 sb.append("Features:");
1015 it = mAvailableFeatures.keySet().iterator();
1016 while (it.hasNext()) {
1017 sb.append(' ');
1018 sb.append(it.next());
1019 }
1020 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001022
1023 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 FileReader permReader = null;
1025 try {
1026 permReader = new FileReader(permFile);
1027 } catch (FileNotFoundException e) {
1028 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
1029 return;
1030 }
1031
1032 try {
1033 XmlPullParser parser = Xml.newPullParser();
1034 parser.setInput(permReader);
1035
1036 XmlUtils.beginDocument(parser, "permissions");
1037
1038 while (true) {
1039 XmlUtils.nextElement(parser);
1040 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1041 break;
1042 }
1043
1044 String name = parser.getName();
1045 if ("group".equals(name)) {
1046 String gidStr = parser.getAttributeValue(null, "gid");
1047 if (gidStr != null) {
1048 int gid = Integer.parseInt(gidStr);
1049 mGlobalGids = appendInt(mGlobalGids, gid);
1050 } else {
1051 Log.w(TAG, "<group> without gid at "
1052 + parser.getPositionDescription());
1053 }
1054
1055 XmlUtils.skipCurrentTag(parser);
1056 continue;
1057 } else if ("permission".equals(name)) {
1058 String perm = parser.getAttributeValue(null, "name");
1059 if (perm == null) {
1060 Log.w(TAG, "<permission> without name at "
1061 + parser.getPositionDescription());
1062 XmlUtils.skipCurrentTag(parser);
1063 continue;
1064 }
1065 perm = perm.intern();
1066 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 } else if ("assign-permission".equals(name)) {
1069 String perm = parser.getAttributeValue(null, "name");
1070 if (perm == null) {
1071 Log.w(TAG, "<assign-permission> without name at "
1072 + parser.getPositionDescription());
1073 XmlUtils.skipCurrentTag(parser);
1074 continue;
1075 }
1076 String uidStr = parser.getAttributeValue(null, "uid");
1077 if (uidStr == null) {
1078 Log.w(TAG, "<assign-permission> without uid at "
1079 + parser.getPositionDescription());
1080 XmlUtils.skipCurrentTag(parser);
1081 continue;
1082 }
1083 int uid = Process.getUidForName(uidStr);
1084 if (uid < 0) {
1085 Log.w(TAG, "<assign-permission> with unknown uid \""
1086 + uidStr + "\" at "
1087 + parser.getPositionDescription());
1088 XmlUtils.skipCurrentTag(parser);
1089 continue;
1090 }
1091 perm = perm.intern();
1092 HashSet<String> perms = mSystemPermissions.get(uid);
1093 if (perms == null) {
1094 perms = new HashSet<String>();
1095 mSystemPermissions.put(uid, perms);
1096 }
1097 perms.add(perm);
1098 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 } else if ("library".equals(name)) {
1101 String lname = parser.getAttributeValue(null, "name");
1102 String lfile = parser.getAttributeValue(null, "file");
1103 if (lname == null) {
1104 Log.w(TAG, "<library> without name at "
1105 + parser.getPositionDescription());
1106 } else if (lfile == null) {
1107 Log.w(TAG, "<library> without file at "
1108 + parser.getPositionDescription());
1109 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001110 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001111 mSharedLibraries.put(lname, lfile);
1112 }
1113 XmlUtils.skipCurrentTag(parser);
1114 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001115
Dianne Hackborn49237342009-08-27 20:08:01 -07001116 } else if ("feature".equals(name)) {
1117 String fname = parser.getAttributeValue(null, "name");
1118 if (fname == null) {
1119 Log.w(TAG, "<feature> without name at "
1120 + parser.getPositionDescription());
1121 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001122 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001123 FeatureInfo fi = new FeatureInfo();
1124 fi.name = fname;
1125 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 }
1127 XmlUtils.skipCurrentTag(parser);
1128 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 } else {
1131 XmlUtils.skipCurrentTag(parser);
1132 continue;
1133 }
1134
1135 }
1136 } catch (XmlPullParserException e) {
1137 Log.w(TAG, "Got execption parsing permissions.", e);
1138 } catch (IOException e) {
1139 Log.w(TAG, "Got execption parsing permissions.", e);
1140 }
1141 }
1142
1143 void readPermission(XmlPullParser parser, String name)
1144 throws IOException, XmlPullParserException {
1145
1146 name = name.intern();
1147
1148 BasePermission bp = mSettings.mPermissions.get(name);
1149 if (bp == null) {
1150 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1151 mSettings.mPermissions.put(name, bp);
1152 }
1153 int outerDepth = parser.getDepth();
1154 int type;
1155 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1156 && (type != XmlPullParser.END_TAG
1157 || parser.getDepth() > outerDepth)) {
1158 if (type == XmlPullParser.END_TAG
1159 || type == XmlPullParser.TEXT) {
1160 continue;
1161 }
1162
1163 String tagName = parser.getName();
1164 if ("group".equals(tagName)) {
1165 String gidStr = parser.getAttributeValue(null, "gid");
1166 if (gidStr != null) {
1167 int gid = Process.getGidForName(gidStr);
1168 bp.gids = appendInt(bp.gids, gid);
1169 } else {
1170 Log.w(TAG, "<group> without gid at "
1171 + parser.getPositionDescription());
1172 }
1173 }
1174 XmlUtils.skipCurrentTag(parser);
1175 }
1176 }
1177
1178 static int[] appendInt(int[] cur, int val) {
1179 if (cur == null) {
1180 return new int[] { val };
1181 }
1182 final int N = cur.length;
1183 for (int i=0; i<N; i++) {
1184 if (cur[i] == val) {
1185 return cur;
1186 }
1187 }
1188 int[] ret = new int[N+1];
1189 System.arraycopy(cur, 0, ret, 0, N);
1190 ret[N] = val;
1191 return ret;
1192 }
1193
1194 static int[] appendInts(int[] cur, int[] add) {
1195 if (add == null) return cur;
1196 if (cur == null) return add;
1197 final int N = add.length;
1198 for (int i=0; i<N; i++) {
1199 cur = appendInt(cur, add[i]);
1200 }
1201 return cur;
1202 }
1203
1204 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001205 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1206 // The package has been uninstalled but has retained data and resources.
1207 return PackageParser.generatePackageInfo(p, null, flags);
1208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 final PackageSetting ps = (PackageSetting)p.mExtras;
1210 if (ps == null) {
1211 return null;
1212 }
1213 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1214 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1215 }
1216
1217 public PackageInfo getPackageInfo(String packageName, int flags) {
1218 synchronized (mPackages) {
1219 PackageParser.Package p = mPackages.get(packageName);
1220 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001221 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 + ": " + p);
1223 if (p != null) {
1224 return generatePackageInfo(p, flags);
1225 }
1226 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1227 return generatePackageInfoFromSettingsLP(packageName, flags);
1228 }
1229 }
1230 return null;
1231 }
1232
Dianne Hackborn47096932010-02-11 15:57:09 -08001233 public String[] currentToCanonicalPackageNames(String[] names) {
1234 String[] out = new String[names.length];
1235 synchronized (mPackages) {
1236 for (int i=names.length-1; i>=0; i--) {
1237 PackageSetting ps = mSettings.mPackages.get(names[i]);
1238 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1239 }
1240 }
1241 return out;
1242 }
1243
1244 public String[] canonicalToCurrentPackageNames(String[] names) {
1245 String[] out = new String[names.length];
1246 synchronized (mPackages) {
1247 for (int i=names.length-1; i>=0; i--) {
1248 String cur = mSettings.mRenamedPackages.get(names[i]);
1249 out[i] = cur != null ? cur : names[i];
1250 }
1251 }
1252 return out;
1253 }
1254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 public int getPackageUid(String packageName) {
1256 synchronized (mPackages) {
1257 PackageParser.Package p = mPackages.get(packageName);
1258 if(p != null) {
1259 return p.applicationInfo.uid;
1260 }
1261 PackageSetting ps = mSettings.mPackages.get(packageName);
1262 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1263 return -1;
1264 }
1265 p = ps.pkg;
1266 return p != null ? p.applicationInfo.uid : -1;
1267 }
1268 }
1269
1270 public int[] getPackageGids(String packageName) {
1271 synchronized (mPackages) {
1272 PackageParser.Package p = mPackages.get(packageName);
1273 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001274 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 + ": " + p);
1276 if (p != null) {
1277 final PackageSetting ps = (PackageSetting)p.mExtras;
1278 final SharedUserSetting suid = ps.sharedUser;
1279 return suid != null ? suid.gids : ps.gids;
1280 }
1281 }
1282 // stupid thing to indicate an error.
1283 return new int[0];
1284 }
1285
1286 public PermissionInfo getPermissionInfo(String name, int flags) {
1287 synchronized (mPackages) {
1288 final BasePermission p = mSettings.mPermissions.get(name);
1289 if (p != null && p.perm != null) {
1290 return PackageParser.generatePermissionInfo(p.perm, flags);
1291 }
1292 return null;
1293 }
1294 }
1295
1296 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1297 synchronized (mPackages) {
1298 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1299 for (BasePermission p : mSettings.mPermissions.values()) {
1300 if (group == null) {
1301 if (p.perm.info.group == null) {
1302 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1303 }
1304 } else {
1305 if (group.equals(p.perm.info.group)) {
1306 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1307 }
1308 }
1309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 if (out.size() > 0) {
1312 return out;
1313 }
1314 return mPermissionGroups.containsKey(group) ? out : null;
1315 }
1316 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1319 synchronized (mPackages) {
1320 return PackageParser.generatePermissionGroupInfo(
1321 mPermissionGroups.get(name), flags);
1322 }
1323 }
1324
1325 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1326 synchronized (mPackages) {
1327 final int N = mPermissionGroups.size();
1328 ArrayList<PermissionGroupInfo> out
1329 = new ArrayList<PermissionGroupInfo>(N);
1330 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1331 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1332 }
1333 return out;
1334 }
1335 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1338 PackageSetting ps = mSettings.mPackages.get(packageName);
1339 if(ps != null) {
1340 if(ps.pkg == null) {
1341 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1342 if(pInfo != null) {
1343 return pInfo.applicationInfo;
1344 }
1345 return null;
1346 }
1347 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1348 }
1349 return null;
1350 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1353 PackageSetting ps = mSettings.mPackages.get(packageName);
1354 if(ps != null) {
1355 if(ps.pkg == null) {
1356 ps.pkg = new PackageParser.Package(packageName);
1357 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001358 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1359 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1360 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
1361 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 }
1363 return generatePackageInfo(ps.pkg, flags);
1364 }
1365 return null;
1366 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1369 synchronized (mPackages) {
1370 PackageParser.Package p = mPackages.get(packageName);
1371 if (Config.LOGV) Log.v(
1372 TAG, "getApplicationInfo " + packageName
1373 + ": " + p);
1374 if (p != null) {
1375 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001376 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 }
1378 if ("android".equals(packageName)||"system".equals(packageName)) {
1379 return mAndroidApplication;
1380 }
1381 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1382 return generateApplicationInfoFromSettingsLP(packageName, flags);
1383 }
1384 }
1385 return null;
1386 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001387
1388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1390 mContext.enforceCallingOrSelfPermission(
1391 android.Manifest.permission.CLEAR_APP_CACHE, null);
1392 // Queue up an async operation since clearing cache may take a little while.
1393 mHandler.post(new Runnable() {
1394 public void run() {
1395 mHandler.removeCallbacks(this);
1396 int retCode = -1;
1397 if (mInstaller != null) {
1398 retCode = mInstaller.freeCache(freeStorageSize);
1399 if (retCode < 0) {
1400 Log.w(TAG, "Couldn't clear application caches");
1401 }
1402 } //end if mInstaller
1403 if (observer != null) {
1404 try {
1405 observer.onRemoveCompleted(null, (retCode >= 0));
1406 } catch (RemoteException e) {
1407 Log.w(TAG, "RemoveException when invoking call back");
1408 }
1409 }
1410 }
1411 });
1412 }
1413
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001414 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001415 mContext.enforceCallingOrSelfPermission(
1416 android.Manifest.permission.CLEAR_APP_CACHE, null);
1417 // Queue up an async operation since clearing cache may take a little while.
1418 mHandler.post(new Runnable() {
1419 public void run() {
1420 mHandler.removeCallbacks(this);
1421 int retCode = -1;
1422 if (mInstaller != null) {
1423 retCode = mInstaller.freeCache(freeStorageSize);
1424 if (retCode < 0) {
1425 Log.w(TAG, "Couldn't clear application caches");
1426 }
1427 }
1428 if(pi != null) {
1429 try {
1430 // Callback via pending intent
1431 int code = (retCode >= 0) ? 1 : 0;
1432 pi.sendIntent(null, code, null,
1433 null, null);
1434 } catch (SendIntentException e1) {
1435 Log.i(TAG, "Failed to send pending intent");
1436 }
1437 }
1438 }
1439 });
1440 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1443 synchronized (mPackages) {
1444 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001445
1446 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001448 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450 if (mResolveComponentName.equals(component)) {
1451 return mResolveActivity;
1452 }
1453 }
1454 return null;
1455 }
1456
1457 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1458 synchronized (mPackages) {
1459 PackageParser.Activity a = mReceivers.mActivities.get(component);
1460 if (Config.LOGV) Log.v(
1461 TAG, "getReceiverInfo " + component + ": " + a);
1462 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1463 return PackageParser.generateActivityInfo(a, flags);
1464 }
1465 }
1466 return null;
1467 }
1468
1469 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1470 synchronized (mPackages) {
1471 PackageParser.Service s = mServices.mServices.get(component);
1472 if (Config.LOGV) Log.v(
1473 TAG, "getServiceInfo " + component + ": " + s);
1474 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1475 return PackageParser.generateServiceInfo(s, flags);
1476 }
1477 }
1478 return null;
1479 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 public String[] getSystemSharedLibraryNames() {
1482 Set<String> libSet;
1483 synchronized (mPackages) {
1484 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001485 int size = libSet.size();
1486 if (size > 0) {
1487 String[] libs = new String[size];
1488 libSet.toArray(libs);
1489 return libs;
1490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001492 return null;
1493 }
1494
1495 public FeatureInfo[] getSystemAvailableFeatures() {
1496 Collection<FeatureInfo> featSet;
1497 synchronized (mPackages) {
1498 featSet = mAvailableFeatures.values();
1499 int size = featSet.size();
1500 if (size > 0) {
1501 FeatureInfo[] features = new FeatureInfo[size+1];
1502 featSet.toArray(features);
1503 FeatureInfo fi = new FeatureInfo();
1504 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1505 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1506 features[size] = fi;
1507 return features;
1508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 }
1510 return null;
1511 }
1512
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001513 public boolean hasSystemFeature(String name) {
1514 synchronized (mPackages) {
1515 return mAvailableFeatures.containsKey(name);
1516 }
1517 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 public int checkPermission(String permName, String pkgName) {
1520 synchronized (mPackages) {
1521 PackageParser.Package p = mPackages.get(pkgName);
1522 if (p != null && p.mExtras != null) {
1523 PackageSetting ps = (PackageSetting)p.mExtras;
1524 if (ps.sharedUser != null) {
1525 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1526 return PackageManager.PERMISSION_GRANTED;
1527 }
1528 } else if (ps.grantedPermissions.contains(permName)) {
1529 return PackageManager.PERMISSION_GRANTED;
1530 }
1531 }
1532 }
1533 return PackageManager.PERMISSION_DENIED;
1534 }
1535
1536 public int checkUidPermission(String permName, int uid) {
1537 synchronized (mPackages) {
1538 Object obj = mSettings.getUserIdLP(uid);
1539 if (obj != null) {
1540 if (obj instanceof SharedUserSetting) {
1541 SharedUserSetting sus = (SharedUserSetting)obj;
1542 if (sus.grantedPermissions.contains(permName)) {
1543 return PackageManager.PERMISSION_GRANTED;
1544 }
1545 } else if (obj instanceof PackageSetting) {
1546 PackageSetting ps = (PackageSetting)obj;
1547 if (ps.grantedPermissions.contains(permName)) {
1548 return PackageManager.PERMISSION_GRANTED;
1549 }
1550 }
1551 } else {
1552 HashSet<String> perms = mSystemPermissions.get(uid);
1553 if (perms != null && perms.contains(permName)) {
1554 return PackageManager.PERMISSION_GRANTED;
1555 }
1556 }
1557 }
1558 return PackageManager.PERMISSION_DENIED;
1559 }
1560
1561 private BasePermission findPermissionTreeLP(String permName) {
1562 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1563 if (permName.startsWith(bp.name) &&
1564 permName.length() > bp.name.length() &&
1565 permName.charAt(bp.name.length()) == '.') {
1566 return bp;
1567 }
1568 }
1569 return null;
1570 }
1571
1572 private BasePermission checkPermissionTreeLP(String permName) {
1573 if (permName != null) {
1574 BasePermission bp = findPermissionTreeLP(permName);
1575 if (bp != null) {
1576 if (bp.uid == Binder.getCallingUid()) {
1577 return bp;
1578 }
1579 throw new SecurityException("Calling uid "
1580 + Binder.getCallingUid()
1581 + " is not allowed to add to permission tree "
1582 + bp.name + " owned by uid " + bp.uid);
1583 }
1584 }
1585 throw new SecurityException("No permission tree found for " + permName);
1586 }
1587
1588 public boolean addPermission(PermissionInfo info) {
1589 synchronized (mPackages) {
1590 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1591 throw new SecurityException("Label must be specified in permission");
1592 }
1593 BasePermission tree = checkPermissionTreeLP(info.name);
1594 BasePermission bp = mSettings.mPermissions.get(info.name);
1595 boolean added = bp == null;
1596 if (added) {
1597 bp = new BasePermission(info.name, tree.sourcePackage,
1598 BasePermission.TYPE_DYNAMIC);
1599 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1600 throw new SecurityException(
1601 "Not allowed to modify non-dynamic permission "
1602 + info.name);
1603 }
1604 bp.perm = new PackageParser.Permission(tree.perm.owner,
1605 new PermissionInfo(info));
1606 bp.perm.info.packageName = tree.perm.info.packageName;
1607 bp.uid = tree.uid;
1608 if (added) {
1609 mSettings.mPermissions.put(info.name, bp);
1610 }
1611 mSettings.writeLP();
1612 return added;
1613 }
1614 }
1615
1616 public void removePermission(String name) {
1617 synchronized (mPackages) {
1618 checkPermissionTreeLP(name);
1619 BasePermission bp = mSettings.mPermissions.get(name);
1620 if (bp != null) {
1621 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1622 throw new SecurityException(
1623 "Not allowed to modify non-dynamic permission "
1624 + name);
1625 }
1626 mSettings.mPermissions.remove(name);
1627 mSettings.writeLP();
1628 }
1629 }
1630 }
1631
Dianne Hackborn854060af2009-07-09 18:14:31 -07001632 public boolean isProtectedBroadcast(String actionName) {
1633 synchronized (mPackages) {
1634 return mProtectedBroadcasts.contains(actionName);
1635 }
1636 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 public int checkSignatures(String pkg1, String pkg2) {
1639 synchronized (mPackages) {
1640 PackageParser.Package p1 = mPackages.get(pkg1);
1641 PackageParser.Package p2 = mPackages.get(pkg2);
1642 if (p1 == null || p1.mExtras == null
1643 || p2 == null || p2.mExtras == null) {
1644 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1645 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001646 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 }
1648 }
1649
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001650 public int checkUidSignatures(int uid1, int uid2) {
1651 synchronized (mPackages) {
1652 Signature[] s1;
1653 Signature[] s2;
1654 Object obj = mSettings.getUserIdLP(uid1);
1655 if (obj != null) {
1656 if (obj instanceof SharedUserSetting) {
1657 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1658 } else if (obj instanceof PackageSetting) {
1659 s1 = ((PackageSetting)obj).signatures.mSignatures;
1660 } else {
1661 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1662 }
1663 } else {
1664 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1665 }
1666 obj = mSettings.getUserIdLP(uid2);
1667 if (obj != null) {
1668 if (obj instanceof SharedUserSetting) {
1669 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1670 } else if (obj instanceof PackageSetting) {
1671 s2 = ((PackageSetting)obj).signatures.mSignatures;
1672 } else {
1673 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1674 }
1675 } else {
1676 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1677 }
1678 return checkSignaturesLP(s1, s2);
1679 }
1680 }
1681
1682 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1683 if (s1 == null) {
1684 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1686 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1687 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001688 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1690 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001691 final int N1 = s1.length;
1692 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 for (int i=0; i<N1; i++) {
1694 boolean match = false;
1695 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001696 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 match = true;
1698 break;
1699 }
1700 }
1701 if (!match) {
1702 return PackageManager.SIGNATURE_NO_MATCH;
1703 }
1704 }
1705 return PackageManager.SIGNATURE_MATCH;
1706 }
1707
1708 public String[] getPackagesForUid(int uid) {
1709 synchronized (mPackages) {
1710 Object obj = mSettings.getUserIdLP(uid);
1711 if (obj instanceof SharedUserSetting) {
1712 SharedUserSetting sus = (SharedUserSetting)obj;
1713 final int N = sus.packages.size();
1714 String[] res = new String[N];
1715 Iterator<PackageSetting> it = sus.packages.iterator();
1716 int i=0;
1717 while (it.hasNext()) {
1718 res[i++] = it.next().name;
1719 }
1720 return res;
1721 } else if (obj instanceof PackageSetting) {
1722 PackageSetting ps = (PackageSetting)obj;
1723 return new String[] { ps.name };
1724 }
1725 }
1726 return null;
1727 }
1728
1729 public String getNameForUid(int uid) {
1730 synchronized (mPackages) {
1731 Object obj = mSettings.getUserIdLP(uid);
1732 if (obj instanceof SharedUserSetting) {
1733 SharedUserSetting sus = (SharedUserSetting)obj;
1734 return sus.name + ":" + sus.userId;
1735 } else if (obj instanceof PackageSetting) {
1736 PackageSetting ps = (PackageSetting)obj;
1737 return ps.name;
1738 }
1739 }
1740 return null;
1741 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 public int getUidForSharedUser(String sharedUserName) {
1744 if(sharedUserName == null) {
1745 return -1;
1746 }
1747 synchronized (mPackages) {
1748 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1749 if(suid == null) {
1750 return -1;
1751 }
1752 return suid.userId;
1753 }
1754 }
1755
1756 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1757 int flags) {
1758 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001759 return chooseBestActivity(intent, resolvedType, flags, query);
1760 }
1761
Mihai Predaeae850c2009-05-13 10:13:48 +02001762 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1763 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 if (query != null) {
1765 final int N = query.size();
1766 if (N == 1) {
1767 return query.get(0);
1768 } else if (N > 1) {
1769 // If there is more than one activity with the same priority,
1770 // then let the user decide between them.
1771 ResolveInfo r0 = query.get(0);
1772 ResolveInfo r1 = query.get(1);
1773 if (false) {
1774 System.out.println(r0.activityInfo.name +
1775 "=" + r0.priority + " vs " +
1776 r1.activityInfo.name +
1777 "=" + r1.priority);
1778 }
1779 // If the first activity has a higher priority, or a different
1780 // default, then it is always desireable to pick it.
1781 if (r0.priority != r1.priority
1782 || r0.preferredOrder != r1.preferredOrder
1783 || r0.isDefault != r1.isDefault) {
1784 return query.get(0);
1785 }
1786 // If we have saved a preference for a preferred activity for
1787 // this Intent, use that.
1788 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1789 flags, query, r0.priority);
1790 if (ri != null) {
1791 return ri;
1792 }
1793 return mResolveInfo;
1794 }
1795 }
1796 return null;
1797 }
1798
1799 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1800 int flags, List<ResolveInfo> query, int priority) {
1801 synchronized (mPackages) {
1802 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1803 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001804 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1806 if (prefs != null && prefs.size() > 0) {
1807 // First figure out how good the original match set is.
1808 // We will only allow preferred activities that came
1809 // from the same match quality.
1810 int match = 0;
1811 final int N = query.size();
1812 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1813 for (int j=0; j<N; j++) {
1814 ResolveInfo ri = query.get(j);
1815 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1816 + ": 0x" + Integer.toHexString(match));
1817 if (ri.match > match) match = ri.match;
1818 }
1819 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1820 + Integer.toHexString(match));
1821 match &= IntentFilter.MATCH_CATEGORY_MASK;
1822 final int M = prefs.size();
1823 for (int i=0; i<M; i++) {
1824 PreferredActivity pa = prefs.get(i);
1825 if (pa.mMatch != match) {
1826 continue;
1827 }
1828 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1829 if (DEBUG_PREFERRED) {
1830 Log.v(TAG, "Got preferred activity:");
1831 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1832 }
1833 if (ai != null) {
1834 for (int j=0; j<N; j++) {
1835 ResolveInfo ri = query.get(j);
1836 if (!ri.activityInfo.applicationInfo.packageName
1837 .equals(ai.applicationInfo.packageName)) {
1838 continue;
1839 }
1840 if (!ri.activityInfo.name.equals(ai.name)) {
1841 continue;
1842 }
1843
1844 // Okay we found a previously set preferred app.
1845 // If the result set is different from when this
1846 // was created, we need to clear it and re-ask the
1847 // user their preference.
1848 if (!pa.sameSet(query, priority)) {
1849 Log.i(TAG, "Result set changed, dropping preferred activity for "
1850 + intent + " type " + resolvedType);
1851 mSettings.mPreferredActivities.removeFilter(pa);
1852 return null;
1853 }
1854
1855 // Yay!
1856 return ri;
1857 }
1858 }
1859 }
1860 }
1861 }
1862 return null;
1863 }
1864
1865 public List<ResolveInfo> queryIntentActivities(Intent intent,
1866 String resolvedType, int flags) {
1867 ComponentName comp = intent.getComponent();
1868 if (comp != null) {
1869 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1870 ActivityInfo ai = getActivityInfo(comp, flags);
1871 if (ai != null) {
1872 ResolveInfo ri = new ResolveInfo();
1873 ri.activityInfo = ai;
1874 list.add(ri);
1875 }
1876 return list;
1877 }
1878
1879 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001880 String pkgName = intent.getPackage();
1881 if (pkgName == null) {
1882 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1883 resolvedType, flags);
1884 }
1885 PackageParser.Package pkg = mPackages.get(pkgName);
1886 if (pkg != null) {
1887 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1888 resolvedType, flags, pkg.activities);
1889 }
1890 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 }
1892 }
1893
1894 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1895 Intent[] specifics, String[] specificTypes, Intent intent,
1896 String resolvedType, int flags) {
1897 final String resultsAction = intent.getAction();
1898
1899 List<ResolveInfo> results = queryIntentActivities(
1900 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1901 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1902
1903 int specificsPos = 0;
1904 int N;
1905
1906 // todo: note that the algorithm used here is O(N^2). This
1907 // isn't a problem in our current environment, but if we start running
1908 // into situations where we have more than 5 or 10 matches then this
1909 // should probably be changed to something smarter...
1910
1911 // First we go through and resolve each of the specific items
1912 // that were supplied, taking care of removing any corresponding
1913 // duplicate items in the generic resolve list.
1914 if (specifics != null) {
1915 for (int i=0; i<specifics.length; i++) {
1916 final Intent sintent = specifics[i];
1917 if (sintent == null) {
1918 continue;
1919 }
1920
1921 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1922 String action = sintent.getAction();
1923 if (resultsAction != null && resultsAction.equals(action)) {
1924 // If this action was explicitly requested, then don't
1925 // remove things that have it.
1926 action = null;
1927 }
1928 ComponentName comp = sintent.getComponent();
1929 ResolveInfo ri = null;
1930 ActivityInfo ai = null;
1931 if (comp == null) {
1932 ri = resolveIntent(
1933 sintent,
1934 specificTypes != null ? specificTypes[i] : null,
1935 flags);
1936 if (ri == null) {
1937 continue;
1938 }
1939 if (ri == mResolveInfo) {
1940 // ACK! Must do something better with this.
1941 }
1942 ai = ri.activityInfo;
1943 comp = new ComponentName(ai.applicationInfo.packageName,
1944 ai.name);
1945 } else {
1946 ai = getActivityInfo(comp, flags);
1947 if (ai == null) {
1948 continue;
1949 }
1950 }
1951
1952 // Look for any generic query activities that are duplicates
1953 // of this specific one, and remove them from the results.
1954 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1955 N = results.size();
1956 int j;
1957 for (j=specificsPos; j<N; j++) {
1958 ResolveInfo sri = results.get(j);
1959 if ((sri.activityInfo.name.equals(comp.getClassName())
1960 && sri.activityInfo.applicationInfo.packageName.equals(
1961 comp.getPackageName()))
1962 || (action != null && sri.filter.matchAction(action))) {
1963 results.remove(j);
1964 if (Config.LOGV) Log.v(
1965 TAG, "Removing duplicate item from " + j
1966 + " due to specific " + specificsPos);
1967 if (ri == null) {
1968 ri = sri;
1969 }
1970 j--;
1971 N--;
1972 }
1973 }
1974
1975 // Add this specific item to its proper place.
1976 if (ri == null) {
1977 ri = new ResolveInfo();
1978 ri.activityInfo = ai;
1979 }
1980 results.add(specificsPos, ri);
1981 ri.specificIndex = i;
1982 specificsPos++;
1983 }
1984 }
1985
1986 // Now we go through the remaining generic results and remove any
1987 // duplicate actions that are found here.
1988 N = results.size();
1989 for (int i=specificsPos; i<N-1; i++) {
1990 final ResolveInfo rii = results.get(i);
1991 if (rii.filter == null) {
1992 continue;
1993 }
1994
1995 // Iterate over all of the actions of this result's intent
1996 // filter... typically this should be just one.
1997 final Iterator<String> it = rii.filter.actionsIterator();
1998 if (it == null) {
1999 continue;
2000 }
2001 while (it.hasNext()) {
2002 final String action = it.next();
2003 if (resultsAction != null && resultsAction.equals(action)) {
2004 // If this action was explicitly requested, then don't
2005 // remove things that have it.
2006 continue;
2007 }
2008 for (int j=i+1; j<N; j++) {
2009 final ResolveInfo rij = results.get(j);
2010 if (rij.filter != null && rij.filter.hasAction(action)) {
2011 results.remove(j);
2012 if (Config.LOGV) Log.v(
2013 TAG, "Removing duplicate item from " + j
2014 + " due to action " + action + " at " + i);
2015 j--;
2016 N--;
2017 }
2018 }
2019 }
2020
2021 // If the caller didn't request filter information, drop it now
2022 // so we don't have to marshall/unmarshall it.
2023 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2024 rii.filter = null;
2025 }
2026 }
2027
2028 // Filter out the caller activity if so requested.
2029 if (caller != null) {
2030 N = results.size();
2031 for (int i=0; i<N; i++) {
2032 ActivityInfo ainfo = results.get(i).activityInfo;
2033 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2034 && caller.getClassName().equals(ainfo.name)) {
2035 results.remove(i);
2036 break;
2037 }
2038 }
2039 }
2040
2041 // If the caller didn't request filter information,
2042 // drop them now so we don't have to
2043 // marshall/unmarshall it.
2044 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2045 N = results.size();
2046 for (int i=0; i<N; i++) {
2047 results.get(i).filter = null;
2048 }
2049 }
2050
2051 if (Config.LOGV) Log.v(TAG, "Result: " + results);
2052 return results;
2053 }
2054
2055 public List<ResolveInfo> queryIntentReceivers(Intent intent,
2056 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002057 ComponentName comp = intent.getComponent();
2058 if (comp != null) {
2059 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2060 ActivityInfo ai = getReceiverInfo(comp, flags);
2061 if (ai != null) {
2062 ResolveInfo ri = new ResolveInfo();
2063 ri.activityInfo = ai;
2064 list.add(ri);
2065 }
2066 return list;
2067 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002070 String pkgName = intent.getPackage();
2071 if (pkgName == null) {
2072 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
2073 resolvedType, flags);
2074 }
2075 PackageParser.Package pkg = mPackages.get(pkgName);
2076 if (pkg != null) {
2077 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
2078 resolvedType, flags, pkg.receivers);
2079 }
2080 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 }
2082 }
2083
2084 public ResolveInfo resolveService(Intent intent, String resolvedType,
2085 int flags) {
2086 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
2087 flags);
2088 if (query != null) {
2089 if (query.size() >= 1) {
2090 // If there is more than one service with the same priority,
2091 // just arbitrarily pick the first one.
2092 return query.get(0);
2093 }
2094 }
2095 return null;
2096 }
2097
2098 public List<ResolveInfo> queryIntentServices(Intent intent,
2099 String resolvedType, int flags) {
2100 ComponentName comp = intent.getComponent();
2101 if (comp != null) {
2102 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2103 ServiceInfo si = getServiceInfo(comp, flags);
2104 if (si != null) {
2105 ResolveInfo ri = new ResolveInfo();
2106 ri.serviceInfo = si;
2107 list.add(ri);
2108 }
2109 return list;
2110 }
2111
2112 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002113 String pkgName = intent.getPackage();
2114 if (pkgName == null) {
2115 return (List<ResolveInfo>)mServices.queryIntent(intent,
2116 resolvedType, flags);
2117 }
2118 PackageParser.Package pkg = mPackages.get(pkgName);
2119 if (pkg != null) {
2120 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
2121 resolvedType, flags, pkg.services);
2122 }
2123 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 }
2125 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 public List<PackageInfo> getInstalledPackages(int flags) {
2128 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2129
2130 synchronized (mPackages) {
2131 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2132 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2133 while (i.hasNext()) {
2134 final PackageSetting ps = i.next();
2135 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2136 if(psPkg != null) {
2137 finalList.add(psPkg);
2138 }
2139 }
2140 }
2141 else {
2142 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2143 while (i.hasNext()) {
2144 final PackageParser.Package p = i.next();
2145 if (p.applicationInfo != null) {
2146 PackageInfo pi = generatePackageInfo(p, flags);
2147 if(pi != null) {
2148 finalList.add(pi);
2149 }
2150 }
2151 }
2152 }
2153 }
2154 return finalList;
2155 }
2156
2157 public List<ApplicationInfo> getInstalledApplications(int flags) {
2158 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2159 synchronized(mPackages) {
2160 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2161 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2162 while (i.hasNext()) {
2163 final PackageSetting ps = i.next();
2164 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2165 if(ai != null) {
2166 finalList.add(ai);
2167 }
2168 }
2169 }
2170 else {
2171 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2172 while (i.hasNext()) {
2173 final PackageParser.Package p = i.next();
2174 if (p.applicationInfo != null) {
2175 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2176 if(ai != null) {
2177 finalList.add(ai);
2178 }
2179 }
2180 }
2181 }
2182 }
2183 return finalList;
2184 }
2185
2186 public List<ApplicationInfo> getPersistentApplications(int flags) {
2187 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2188
2189 synchronized (mPackages) {
2190 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2191 while (i.hasNext()) {
2192 PackageParser.Package p = i.next();
2193 if (p.applicationInfo != null
2194 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
2195 && (!mSafeMode || (p.applicationInfo.flags
2196 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2197 finalList.add(p.applicationInfo);
2198 }
2199 }
2200 }
2201
2202 return finalList;
2203 }
2204
2205 public ProviderInfo resolveContentProvider(String name, int flags) {
2206 synchronized (mPackages) {
2207 final PackageParser.Provider provider = mProviders.get(name);
2208 return provider != null
2209 && mSettings.isEnabledLP(provider.info, flags)
2210 && (!mSafeMode || (provider.info.applicationInfo.flags
2211 &ApplicationInfo.FLAG_SYSTEM) != 0)
2212 ? PackageParser.generateProviderInfo(provider, flags)
2213 : null;
2214 }
2215 }
2216
Fred Quintana718d8a22009-04-29 17:53:20 -07002217 /**
2218 * @deprecated
2219 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 public void querySyncProviders(List outNames, List outInfo) {
2221 synchronized (mPackages) {
2222 Iterator<Map.Entry<String, PackageParser.Provider>> i
2223 = mProviders.entrySet().iterator();
2224
2225 while (i.hasNext()) {
2226 Map.Entry<String, PackageParser.Provider> entry = i.next();
2227 PackageParser.Provider p = entry.getValue();
2228
2229 if (p.syncable
2230 && (!mSafeMode || (p.info.applicationInfo.flags
2231 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2232 outNames.add(entry.getKey());
2233 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2234 }
2235 }
2236 }
2237 }
2238
2239 public List<ProviderInfo> queryContentProviders(String processName,
2240 int uid, int flags) {
2241 ArrayList<ProviderInfo> finalList = null;
2242
2243 synchronized (mPackages) {
2244 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2245 while (i.hasNext()) {
2246 PackageParser.Provider p = i.next();
2247 if (p.info.authority != null
2248 && (processName == null ||
2249 (p.info.processName.equals(processName)
2250 && p.info.applicationInfo.uid == uid))
2251 && mSettings.isEnabledLP(p.info, flags)
2252 && (!mSafeMode || (p.info.applicationInfo.flags
2253 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2254 if (finalList == null) {
2255 finalList = new ArrayList<ProviderInfo>(3);
2256 }
2257 finalList.add(PackageParser.generateProviderInfo(p,
2258 flags));
2259 }
2260 }
2261 }
2262
2263 if (finalList != null) {
2264 Collections.sort(finalList, mProviderInitOrderSorter);
2265 }
2266
2267 return finalList;
2268 }
2269
2270 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2271 int flags) {
2272 synchronized (mPackages) {
2273 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2274 return PackageParser.generateInstrumentationInfo(i, flags);
2275 }
2276 }
2277
2278 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2279 int flags) {
2280 ArrayList<InstrumentationInfo> finalList =
2281 new ArrayList<InstrumentationInfo>();
2282
2283 synchronized (mPackages) {
2284 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2285 while (i.hasNext()) {
2286 PackageParser.Instrumentation p = i.next();
2287 if (targetPackage == null
2288 || targetPackage.equals(p.info.targetPackage)) {
2289 finalList.add(PackageParser.generateInstrumentationInfo(p,
2290 flags));
2291 }
2292 }
2293 }
2294
2295 return finalList;
2296 }
2297
2298 private void scanDirLI(File dir, int flags, int scanMode) {
2299 Log.d(TAG, "Scanning app dir " + dir);
2300
2301 String[] files = dir.list();
2302
2303 int i;
2304 for (i=0; i<files.length; i++) {
2305 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002306 if (!isPackageFilename(files[i])) {
2307 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002308 continue;
2309 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002310 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002312 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002313 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2314 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002315 // Delete the apk
2316 Log.w(TAG, "Cleaning up failed install of " + file);
2317 file.delete();
2318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 }
2320 }
2321
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002322 private static File getSettingsProblemFile() {
2323 File dataDir = Environment.getDataDirectory();
2324 File systemDir = new File(dataDir, "system");
2325 File fname = new File(systemDir, "uiderrors.txt");
2326 return fname;
2327 }
2328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329 private static void reportSettingsProblem(int priority, String msg) {
2330 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002331 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 FileOutputStream out = new FileOutputStream(fname, true);
2333 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002334 SimpleDateFormat formatter = new SimpleDateFormat();
2335 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2336 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 pw.close();
2338 FileUtils.setPermissions(
2339 fname.toString(),
2340 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2341 -1, -1);
2342 } catch (java.io.IOException e) {
2343 }
2344 Log.println(priority, TAG, msg);
2345 }
2346
2347 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2348 PackageParser.Package pkg, File srcFile, int parseFlags) {
2349 if (GET_CERTIFICATES) {
2350 if (ps == null || !ps.codePath.equals(srcFile)
2351 || ps.getTimeStamp() != srcFile.lastModified()) {
2352 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2353 if (!pp.collectCertificates(pkg, parseFlags)) {
2354 mLastScanError = pp.getParseError();
2355 return false;
2356 }
2357 }
2358 }
2359 return true;
2360 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 /*
2363 * Scan a package and return the newly parsed package.
2364 * Returns null in case of errors and the error code is stored in mLastScanError
2365 */
2366 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002367 int parseFlags, int scanMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002369 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002370 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002371 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002374 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 if (pkg == null) {
2376 mLastScanError = pp.getParseError();
2377 return null;
2378 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002379 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002380 PackageSetting updatedPkg;
2381 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002382 // Look to see if we already know about this package.
2383 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002384 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002385 // This package has been renamed to its original name. Let's
2386 // use that.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002387 ps = mSettings.peekPackageLP(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002388 }
2389 // If there was no original package, see one for the real package name.
2390 if (ps == null) {
2391 ps = mSettings.peekPackageLP(pkg.packageName);
2392 }
2393 // Check to see if this package could be hiding/updating a system
2394 // package. Must look for it either under the original or real
2395 // package name depending on our state.
2396 updatedPkg = mSettings.mDisabledSysPackages.get(
2397 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002399 // First check if this is a system package that may involve an update
2400 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2401 if (!ps.codePath.equals(scanFile)) {
2402 // The path has changed from what was last scanned... check the
2403 // version of the new path against what we have stored to determine
2404 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002405 if (pkg.mVersionCode < ps.versionCode) {
2406 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002407 // Ignore entry. Skip it.
2408 Log.i(TAG, "Package " + ps.name + " at " + scanFile
2409 + "ignored: updated version " + ps.versionCode
2410 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002411 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2412 return null;
2413 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002414 // The current app on the system partion is better than
2415 // what we have updated to on the data partition; switch
2416 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002417 // At this point, its safely assumed that package installation for
2418 // apps in system partition will go through. If not there won't be a working
2419 // version of the app
2420 synchronized (mPackages) {
2421 // Just remove the loaded entries from package lists.
2422 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002423 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002424 Log.w(TAG, "Package " + ps.name + " at " + scanFile
2425 + "reverting from " + ps.codePathString
2426 + ": new version " + pkg.mVersionCode
2427 + " better than installed " + ps.versionCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002428 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2429 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002430 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 }
2433 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002434 if (updatedPkg != null) {
2435 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2436 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2437 }
2438 // Verify certificates against what was last scanned
2439 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2440 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2441 return null;
2442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002443 // The apk is forward locked (not public) if its code and resources
2444 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002445 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002446 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002447 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002448 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002449
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002450 String codePath = null;
2451 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002452 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2453 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002454 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002455 } else {
2456 // Should not happen at all. Just log an error.
2457 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2458 }
2459 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002460 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002461 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002462 codePath = pkg.mScanPath;
2463 // Set application objects path explicitly.
2464 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002466 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 }
2468
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002469 private static void setApplicationInfoPaths(PackageParser.Package pkg,
2470 String destCodePath, String destResPath) {
2471 pkg.mPath = pkg.mScanPath = destCodePath;
2472 pkg.applicationInfo.sourceDir = destCodePath;
2473 pkg.applicationInfo.publicSourceDir = destResPath;
2474 }
2475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 private static String fixProcessName(String defProcessName,
2477 String processName, int uid) {
2478 if (processName == null) {
2479 return defProcessName;
2480 }
2481 return processName;
2482 }
2483
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002484 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2486 if (pkg.mSignatures != null) {
2487 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2488 updateSignature)) {
2489 Log.e(TAG, "Package " + pkg.packageName
2490 + " signatures do not match the previously installed version; ignoring!");
2491 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2492 return false;
2493 }
2494
2495 if (pkgSetting.sharedUser != null) {
2496 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2497 pkg.mSignatures, updateSignature)) {
2498 Log.e(TAG, "Package " + pkg.packageName
2499 + " has no signatures that match those in shared user "
2500 + pkgSetting.sharedUser.name + "; ignoring!");
2501 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2502 return false;
2503 }
2504 }
2505 } else {
2506 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2507 }
2508 return true;
2509 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002510
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002511 public boolean performDexOpt(String packageName) {
2512 if (!mNoDexOpt) {
2513 return false;
2514 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002515
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002516 PackageParser.Package p;
2517 synchronized (mPackages) {
2518 p = mPackages.get(packageName);
2519 if (p == null || p.mDidDexOpt) {
2520 return false;
2521 }
2522 }
2523 synchronized (mInstallLock) {
2524 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2525 }
2526 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002527
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002528 static final int DEX_OPT_SKIPPED = 0;
2529 static final int DEX_OPT_PERFORMED = 1;
2530 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002531
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002532 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2533 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002534 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002535 String path = pkg.mScanPath;
2536 int ret = 0;
2537 try {
2538 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002539 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002540 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002541 pkg.mDidDexOpt = true;
2542 performed = true;
2543 }
2544 } catch (FileNotFoundException e) {
2545 Log.w(TAG, "Apk not found for dexopt: " + path);
2546 ret = -1;
2547 } catch (IOException e) {
2548 Log.w(TAG, "Exception reading apk: " + path, e);
2549 ret = -1;
2550 }
2551 if (ret < 0) {
2552 //error from installer
2553 return DEX_OPT_FAILED;
2554 }
2555 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002556
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002557 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2558 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002559
2560 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2561 return Environment.isEncryptedFilesystemEnabled() &&
2562 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2563 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002564
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002565 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2566 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2567 Log.w(TAG, "Unable to update from " + oldPkg.name
2568 + " to " + newPkg.packageName
2569 + ": old package not in system partition");
2570 return false;
2571 } else if (mPackages.get(oldPkg.name) != null) {
2572 Log.w(TAG, "Unable to update from " + oldPkg.name
2573 + " to " + newPkg.packageName
2574 + ": old package still exists");
2575 return false;
2576 }
2577 return true;
2578 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002579
2580 private File getDataPathForPackage(PackageParser.Package pkg) {
2581 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2582 File dataPath;
2583 if (useEncryptedFSDir) {
2584 dataPath = new File(mSecureAppDataDir, pkg.packageName);
2585 } else {
2586 dataPath = new File(mAppDataDir, pkg.packageName);
2587 }
2588 return dataPath;
2589 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002590
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002591 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
2592 int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002593 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002594 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2595 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002596 // Bail out. The resource and code paths haven't been set.
2597 Log.w(TAG, " Code and resource paths haven't been set correctly");
2598 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2599 return null;
2600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002601 mScanningPath = scanFile;
2602 if (pkg == null) {
2603 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2604 return null;
2605 }
2606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2608 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2609 }
2610
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002611 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 synchronized (mPackages) {
2613 if (mAndroidApplication != null) {
2614 Log.w(TAG, "*************************************************");
2615 Log.w(TAG, "Core android package being redefined. Skipping.");
2616 Log.w(TAG, " file=" + mScanningPath);
2617 Log.w(TAG, "*************************************************");
2618 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2619 return null;
2620 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 // Set up information for our fall-back user intent resolution
2623 // activity.
2624 mPlatformPackage = pkg;
2625 pkg.mVersionCode = mSdkVersion;
2626 mAndroidApplication = pkg.applicationInfo;
2627 mResolveActivity.applicationInfo = mAndroidApplication;
2628 mResolveActivity.name = ResolverActivity.class.getName();
2629 mResolveActivity.packageName = mAndroidApplication.packageName;
2630 mResolveActivity.processName = mAndroidApplication.processName;
2631 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2632 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2633 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2634 mResolveActivity.exported = true;
2635 mResolveActivity.enabled = true;
2636 mResolveInfo.activityInfo = mResolveActivity;
2637 mResolveInfo.priority = 0;
2638 mResolveInfo.preferredOrder = 0;
2639 mResolveInfo.match = 0;
2640 mResolveComponentName = new ComponentName(
2641 mAndroidApplication.packageName, mResolveActivity.name);
2642 }
2643 }
2644
2645 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002646 TAG, "Scanning package " + pkg.packageName);
2647 if (mPackages.containsKey(pkg.packageName)
2648 || mSharedLibraries.containsKey(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 Log.w(TAG, "*************************************************");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002650 Log.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 + " already installed. Skipping duplicate.");
2652 Log.w(TAG, "*************************************************");
2653 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2654 return null;
2655 }
2656
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002657 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002658 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2659 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 SharedUserSetting suid = null;
2662 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002665
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002666 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2667 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002668 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002669 pkg.mRealPackage = null;
2670 pkg.mAdoptPermissions = null;
2671 }
2672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002673 synchronized (mPackages) {
2674 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002675 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2676 if (mTmpSharedLibraries == null ||
2677 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2678 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2679 }
2680 int num = 0;
2681 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2682 for (int i=0; i<N; i++) {
2683 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 if (file == null) {
2685 Log.e(TAG, "Package " + pkg.packageName
2686 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002687 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2689 return null;
2690 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002691 mTmpSharedLibraries[num] = file;
2692 num++;
2693 }
2694 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2695 for (int i=0; i<N; i++) {
2696 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2697 if (file == null) {
2698 Log.w(TAG, "Package " + pkg.packageName
2699 + " desires unavailable shared library "
2700 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2701 } else {
2702 mTmpSharedLibraries[num] = file;
2703 num++;
2704 }
2705 }
2706 if (num > 0) {
2707 pkg.usesLibraryFiles = new String[num];
2708 System.arraycopy(mTmpSharedLibraries, 0,
2709 pkg.usesLibraryFiles, 0, num);
2710 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002711
Dianne Hackborn49237342009-08-27 20:08:01 -07002712 if (pkg.reqFeatures != null) {
2713 N = pkg.reqFeatures.size();
2714 for (int i=0; i<N; i++) {
2715 FeatureInfo fi = pkg.reqFeatures.get(i);
2716 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2717 // Don't care.
2718 continue;
2719 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002720
Dianne Hackborn49237342009-08-27 20:08:01 -07002721 if (fi.name != null) {
2722 if (mAvailableFeatures.get(fi.name) == null) {
2723 Log.e(TAG, "Package " + pkg.packageName
2724 + " requires unavailable feature "
2725 + fi.name + "; failing!");
2726 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2727 return null;
2728 }
2729 }
2730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 }
2732 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 if (pkg.mSharedUserId != null) {
2735 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2736 pkg.applicationInfo.flags, true);
2737 if (suid == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002738 Log.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739 + " for shared user failed");
2740 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2741 return null;
2742 }
2743 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2744 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2745 + suid.userId + "): packages=" + suid.packages);
2746 }
2747 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002748
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002749 if (false) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002750 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002751 Log.w(TAG, "WAITING FOR DEBUGGER");
2752 Debug.waitForDebugger();
Dianne Hackbornc1552392010-03-03 16:19:01 -08002753 Log.i(TAG, "Package " + pkg.packageName + " from original packages"
2754 + pkg.mOriginalPackages);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002755 }
2756 }
2757
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002758 // Check if we are renaming from an original package name.
2759 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002760 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08002761 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002762 // This package may need to be renamed to a previously
2763 // installed name. Let's check on that...
2764 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002765 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002766 // This package had originally been installed as the
2767 // original name, and we have already taken care of
2768 // transitioning to the new one. Just update the new
2769 // one to continue using the old name.
2770 realName = pkg.mRealPackage;
2771 if (!pkg.packageName.equals(renamed)) {
2772 // Callers into this function may have already taken
2773 // care of renaming the package; only do it here if
2774 // it is not already done.
2775 pkg.setPackageName(renamed);
2776 }
2777
Dianne Hackbornc1552392010-03-03 16:19:01 -08002778 } else {
2779 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
2780 if ((origPackage=mSettings.peekPackageLP(
2781 pkg.mOriginalPackages.get(i))) != null) {
2782 // We do have the package already installed under its
2783 // original name... should we use it?
2784 if (!verifyPackageUpdate(origPackage, pkg)) {
2785 // New package is not compatible with original.
2786 origPackage = null;
2787 continue;
2788 } else if (origPackage.sharedUser != null) {
2789 // Make sure uid is compatible between packages.
2790 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
2791 Log.w(TAG, "Unable to migrate data from " + origPackage.name
2792 + " to " + pkg.packageName + ": old uid "
2793 + origPackage.sharedUser.name
2794 + " differs from " + pkg.mSharedUserId);
2795 origPackage = null;
2796 continue;
2797 }
2798 } else {
2799 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
2800 + pkg.packageName + " to old name " + origPackage.name);
2801 }
2802 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002803 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002804 }
2805 }
2806 }
2807
2808 if (mTransferedPackages.contains(pkg.packageName)) {
2809 Log.w(TAG, "Package " + pkg.packageName
2810 + " was transferred to another, but its .apk remains");
2811 }
2812
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002813 // Just create the setting, don't add it yet. For already existing packages
2814 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002815 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 destResourceFile, pkg.applicationInfo.flags, true, false);
2817 if (pkgSetting == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002818 Log.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2820 return null;
2821 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002822
2823 if (pkgSetting.origPackage != null) {
2824 // If we are first transitioning from an original package,
2825 // fix up the new package's name now. We need to do this after
2826 // looking up the package under its new name, so getPackageLP
2827 // can take care of fiddling things correctly.
2828 pkg.setPackageName(origPackage.name);
2829
2830 // File a report about this.
2831 String msg = "New package " + pkgSetting.realName
2832 + " renamed to replace old package " + pkgSetting.name;
2833 reportSettingsProblem(Log.WARN, msg);
2834
2835 // Make a note of it.
2836 mTransferedPackages.add(origPackage.name);
2837
2838 // No longer need to retain this.
2839 pkgSetting.origPackage = null;
2840 }
2841
2842 if (realName != null) {
2843 // Make a note of it.
2844 mTransferedPackages.add(pkg.packageName);
2845 }
2846
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002847 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2849 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 pkg.applicationInfo.uid = pkgSetting.userId;
2852 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002853
2854 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2856 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2857 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2858 return null;
2859 }
2860 // The signature has changed, but this package is in the system
2861 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002862 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 // However... if this package is part of a shared user, but it
2864 // doesn't match the signature of the shared user, let's fail.
2865 // What this means is that you can't change the signatures
2866 // associated with an overall shared user, which doesn't seem all
2867 // that unreasonable.
2868 if (pkgSetting.sharedUser != null) {
2869 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2870 pkg.mSignatures, false)) {
2871 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2872 return null;
2873 }
2874 }
2875 removeExisting = true;
2876 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002877
The Android Open Source Project10592532009-03-18 17:39:46 -07002878 // Verify that this new package doesn't have any content providers
2879 // that conflict with existing packages. Only do this if the
2880 // package isn't already installed, since we don't want to break
2881 // things that are installed.
2882 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2883 int N = pkg.providers.size();
2884 int i;
2885 for (i=0; i<N; i++) {
2886 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08002887 if (p.info.authority != null) {
2888 String names[] = p.info.authority.split(";");
2889 for (int j = 0; j < names.length; j++) {
2890 if (mProviders.containsKey(names[j])) {
2891 PackageParser.Provider other = mProviders.get(names[j]);
2892 Log.w(TAG, "Can't install because provider name " + names[j] +
2893 " (in package " + pkg.applicationInfo.packageName +
2894 ") is already used by "
2895 + ((other != null && other.getComponentName() != null)
2896 ? other.getComponentName().getPackageName() : "?"));
2897 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2898 return null;
2899 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002900 }
2901 }
2902 }
2903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 }
2905
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002906 final String pkgName = pkg.packageName;
2907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002909 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002911 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 if (ret != 0) {
2913 String msg = "System package " + pkg.packageName
2914 + " could not have data directory erased after signature change.";
2915 reportSettingsProblem(Log.WARN, msg);
2916 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2917 return null;
2918 }
2919 }
2920 Log.w(TAG, "System package " + pkg.packageName
2921 + " signature changed: existing data removed.");
2922 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2923 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002924
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002925 if (pkg.mAdoptPermissions != null) {
2926 // This package wants to adopt ownership of permissions from
2927 // another package.
2928 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
2929 String origName = pkg.mAdoptPermissions.get(i);
2930 PackageSetting orig = mSettings.peekPackageLP(origName);
2931 if (orig != null) {
2932 if (verifyPackageUpdate(orig, pkg)) {
2933 Log.i(TAG, "Adopting permissions from "
2934 + origName + " to " + pkg.packageName);
2935 mSettings.transferPermissions(origName, pkg.packageName);
2936 }
2937 }
2938 }
2939 }
2940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 long scanFileTime = scanFile.lastModified();
2942 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2943 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2944 pkg.applicationInfo.processName = fixProcessName(
2945 pkg.applicationInfo.packageName,
2946 pkg.applicationInfo.processName,
2947 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948
2949 File dataPath;
2950 if (mPlatformPackage == pkg) {
2951 // The system package is special.
2952 dataPath = new File (Environment.getDataDirectory(), "system");
2953 pkg.applicationInfo.dataDir = dataPath.getPath();
2954 } else {
2955 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002956 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002957 dataPath = getDataPathForPackage(pkg);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002958
2959 boolean uidError = false;
2960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 if (dataPath.exists()) {
2962 mOutPermissions[1] = 0;
2963 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2964 if (mOutPermissions[1] == pkg.applicationInfo.uid
2965 || !Process.supportsProcesses()) {
2966 pkg.applicationInfo.dataDir = dataPath.getPath();
2967 } else {
2968 boolean recovered = false;
2969 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2970 // If this is a system app, we can at least delete its
2971 // current data so the application will still work.
2972 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002973 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002974 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 // Old data gone!
2976 String msg = "System package " + pkg.packageName
2977 + " has changed from uid: "
2978 + mOutPermissions[1] + " to "
2979 + pkg.applicationInfo.uid + "; old data erased";
2980 reportSettingsProblem(Log.WARN, msg);
2981 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002984 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 pkg.applicationInfo.uid);
2986 if (ret == -1) {
2987 // Ack should not happen!
2988 msg = "System package " + pkg.packageName
2989 + " could not have data directory re-created after delete.";
2990 reportSettingsProblem(Log.WARN, msg);
2991 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2992 return null;
2993 }
2994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002996 if (!recovered) {
2997 mHasSystemUidErrors = true;
2998 }
2999 }
3000 if (!recovered) {
3001 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3002 + pkg.applicationInfo.uid + "/fs_"
3003 + mOutPermissions[1];
3004 String msg = "Package " + pkg.packageName
3005 + " has mismatched uid: "
3006 + mOutPermissions[1] + " on disk, "
3007 + pkg.applicationInfo.uid + " in settings";
3008 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003009 mSettings.mReadMessages.append(msg);
3010 mSettings.mReadMessages.append('\n');
3011 uidError = true;
3012 if (!pkgSetting.uidError) {
3013 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 }
3016 }
3017 }
3018 pkg.applicationInfo.dataDir = dataPath.getPath();
3019 } else {
3020 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
3021 Log.v(TAG, "Want this data dir: " + dataPath);
3022 //invoke installer to do the actual installation
3023 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08003024 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 pkg.applicationInfo.uid);
3026 if(ret < 0) {
3027 // Error from installer
3028 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3029 return null;
3030 }
3031 } else {
3032 dataPath.mkdirs();
3033 if (dataPath.exists()) {
3034 FileUtils.setPermissions(
3035 dataPath.toString(),
3036 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3037 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
3038 }
3039 }
3040 if (dataPath.exists()) {
3041 pkg.applicationInfo.dataDir = dataPath.getPath();
3042 } else {
3043 Log.w(TAG, "Unable to create data directory: " + dataPath);
3044 pkg.applicationInfo.dataDir = null;
3045 }
3046 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003047
3048 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
3050
3051 // Perform shared library installation and dex validation and
3052 // optimization, if this is not a system app.
3053 if (mInstaller != null) {
3054 String path = scanFile.getPath();
3055 if (scanFileNewer) {
3056 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07003057 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
3058 if (err != PackageManager.INSTALL_SUCCEEDED) {
3059 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 return null;
3061 }
3062 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003063 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003064
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003065 if ((scanMode&SCAN_NO_DEX) == 0) {
3066 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3068 return null;
3069 }
3070 }
3071 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 if (mFactoryTest && pkg.requestedPermissions.contains(
3074 android.Manifest.permission.FACTORY_TEST)) {
3075 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3076 }
3077
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003078 // Request the ActivityManager to kill the process(only for existing packages)
3079 // so that we do not end up in a confused state while the user is still using the older
3080 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003081 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003082 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003083 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003084 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003087 // We don't expect installation to fail beyond this point,
3088 if ((scanMode&SCAN_MONITOR) != 0) {
3089 mAppDirs.put(pkg.mPath, pkg);
3090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003092 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003094 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003095 // Make sure we don't accidentally delete its data.
3096 mSettings.mPackagesToBeCleaned.remove(pkgName);
3097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003098 int N = pkg.providers.size();
3099 StringBuilder r = null;
3100 int i;
3101 for (i=0; i<N; i++) {
3102 PackageParser.Provider p = pkg.providers.get(i);
3103 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3104 p.info.processName, pkg.applicationInfo.uid);
3105 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3106 p.info.name), p);
3107 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003108 if (p.info.authority != null) {
3109 String names[] = p.info.authority.split(";");
3110 p.info.authority = null;
3111 for (int j = 0; j < names.length; j++) {
3112 if (j == 1 && p.syncable) {
3113 // We only want the first authority for a provider to possibly be
3114 // syncable, so if we already added this provider using a different
3115 // authority clear the syncable flag. We copy the provider before
3116 // changing it because the mProviders object contains a reference
3117 // to a provider that we don't want to change.
3118 // Only do this for the second authority since the resulting provider
3119 // object can be the same for all future authorities for this provider.
3120 p = new PackageParser.Provider(p);
3121 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003122 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003123 if (!mProviders.containsKey(names[j])) {
3124 mProviders.put(names[j], p);
3125 if (p.info.authority == null) {
3126 p.info.authority = names[j];
3127 } else {
3128 p.info.authority = p.info.authority + ";" + names[j];
3129 }
3130 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
3131 Log.d(TAG, "Registered content provider: " + names[j] +
3132 ", className = " + p.info.name +
3133 ", isSyncable = " + p.info.isSyncable);
3134 } else {
3135 PackageParser.Provider other = mProviders.get(names[j]);
3136 Log.w(TAG, "Skipping provider name " + names[j] +
3137 " (in package " + pkg.applicationInfo.packageName +
3138 "): name already used by "
3139 + ((other != null && other.getComponentName() != null)
3140 ? other.getComponentName().getPackageName() : "?"));
3141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 }
3143 }
3144 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3145 if (r == null) {
3146 r = new StringBuilder(256);
3147 } else {
3148 r.append(' ');
3149 }
3150 r.append(p.info.name);
3151 }
3152 }
3153 if (r != null) {
3154 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3155 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 N = pkg.services.size();
3158 r = null;
3159 for (i=0; i<N; i++) {
3160 PackageParser.Service s = pkg.services.get(i);
3161 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3162 s.info.processName, pkg.applicationInfo.uid);
3163 mServices.addService(s);
3164 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3165 if (r == null) {
3166 r = new StringBuilder(256);
3167 } else {
3168 r.append(' ');
3169 }
3170 r.append(s.info.name);
3171 }
3172 }
3173 if (r != null) {
3174 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3175 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 N = pkg.receivers.size();
3178 r = null;
3179 for (i=0; i<N; i++) {
3180 PackageParser.Activity a = pkg.receivers.get(i);
3181 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3182 a.info.processName, pkg.applicationInfo.uid);
3183 mReceivers.addActivity(a, "receiver");
3184 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3185 if (r == null) {
3186 r = new StringBuilder(256);
3187 } else {
3188 r.append(' ');
3189 }
3190 r.append(a.info.name);
3191 }
3192 }
3193 if (r != null) {
3194 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 N = pkg.activities.size();
3198 r = null;
3199 for (i=0; i<N; i++) {
3200 PackageParser.Activity a = pkg.activities.get(i);
3201 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3202 a.info.processName, pkg.applicationInfo.uid);
3203 mActivities.addActivity(a, "activity");
3204 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3205 if (r == null) {
3206 r = new StringBuilder(256);
3207 } else {
3208 r.append(' ');
3209 }
3210 r.append(a.info.name);
3211 }
3212 }
3213 if (r != null) {
3214 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3215 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 N = pkg.permissionGroups.size();
3218 r = null;
3219 for (i=0; i<N; i++) {
3220 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3221 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3222 if (cur == null) {
3223 mPermissionGroups.put(pg.info.name, pg);
3224 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3225 if (r == null) {
3226 r = new StringBuilder(256);
3227 } else {
3228 r.append(' ');
3229 }
3230 r.append(pg.info.name);
3231 }
3232 } else {
3233 Log.w(TAG, "Permission group " + pg.info.name + " from package "
3234 + pg.info.packageName + " ignored: original from "
3235 + cur.info.packageName);
3236 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3237 if (r == null) {
3238 r = new StringBuilder(256);
3239 } else {
3240 r.append(' ');
3241 }
3242 r.append("DUP:");
3243 r.append(pg.info.name);
3244 }
3245 }
3246 }
3247 if (r != null) {
3248 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3249 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 N = pkg.permissions.size();
3252 r = null;
3253 for (i=0; i<N; i++) {
3254 PackageParser.Permission p = pkg.permissions.get(i);
3255 HashMap<String, BasePermission> permissionMap =
3256 p.tree ? mSettings.mPermissionTrees
3257 : mSettings.mPermissions;
3258 p.group = mPermissionGroups.get(p.info.group);
3259 if (p.info.group == null || p.group != null) {
3260 BasePermission bp = permissionMap.get(p.info.name);
3261 if (bp == null) {
3262 bp = new BasePermission(p.info.name, p.info.packageName,
3263 BasePermission.TYPE_NORMAL);
3264 permissionMap.put(p.info.name, bp);
3265 }
3266 if (bp.perm == null) {
3267 if (bp.sourcePackage == null
3268 || bp.sourcePackage.equals(p.info.packageName)) {
3269 BasePermission tree = findPermissionTreeLP(p.info.name);
3270 if (tree == null
3271 || tree.sourcePackage.equals(p.info.packageName)) {
3272 bp.perm = p;
3273 bp.uid = pkg.applicationInfo.uid;
3274 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3275 if (r == null) {
3276 r = new StringBuilder(256);
3277 } else {
3278 r.append(' ');
3279 }
3280 r.append(p.info.name);
3281 }
3282 } else {
3283 Log.w(TAG, "Permission " + p.info.name + " from package "
3284 + p.info.packageName + " ignored: base tree "
3285 + tree.name + " is from package "
3286 + tree.sourcePackage);
3287 }
3288 } else {
3289 Log.w(TAG, "Permission " + p.info.name + " from package "
3290 + p.info.packageName + " ignored: original from "
3291 + bp.sourcePackage);
3292 }
3293 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3294 if (r == null) {
3295 r = new StringBuilder(256);
3296 } else {
3297 r.append(' ');
3298 }
3299 r.append("DUP:");
3300 r.append(p.info.name);
3301 }
3302 } else {
3303 Log.w(TAG, "Permission " + p.info.name + " from package "
3304 + p.info.packageName + " ignored: no group "
3305 + p.group);
3306 }
3307 }
3308 if (r != null) {
3309 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3310 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 N = pkg.instrumentation.size();
3313 r = null;
3314 for (i=0; i<N; i++) {
3315 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3316 a.info.packageName = pkg.applicationInfo.packageName;
3317 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3318 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3319 a.info.dataDir = pkg.applicationInfo.dataDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003320 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003321 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3322 if (r == null) {
3323 r = new StringBuilder(256);
3324 } else {
3325 r.append(' ');
3326 }
3327 r.append(a.info.name);
3328 }
3329 }
3330 if (r != null) {
3331 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3332 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003333
Dianne Hackborn854060af2009-07-09 18:14:31 -07003334 if (pkg.protectedBroadcasts != null) {
3335 N = pkg.protectedBroadcasts.size();
3336 for (i=0; i<N; i++) {
3337 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3338 }
3339 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 pkgSetting.setTimeStamp(scanFileTime);
3342 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 return pkg;
3345 }
3346
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003347 private void killApplication(String pkgName, int uid) {
3348 // Request the ActivityManager to kill the process(only for existing packages)
3349 // so that we do not end up in a confused state while the user is still using the older
3350 // version of the application while the new one gets installed.
3351 IActivityManager am = ActivityManagerNative.getDefault();
3352 if (am != null) {
3353 try {
3354 am.killApplicationWithUid(pkgName, uid);
3355 } catch (RemoteException e) {
3356 }
3357 }
3358 }
3359
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003360 // The following constants are returned by cachePackageSharedLibsForAbiLI
3361 // to indicate if native shared libraries were found in the package.
3362 // Values are:
3363 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
3364 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
3365 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
3366 // in package (and not installed)
3367 //
3368 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
3369 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
3370 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003371
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003372 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
3373 // and automatically copy them to /data/data/<appname>/lib if present.
3374 //
3375 // NOTE: this method may throw an IOException if the library cannot
3376 // be copied to its final destination, e.g. if there isn't enough
3377 // room left on the data partition, or a ZipException if the package
3378 // file is malformed.
3379 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003380 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
3381 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003382 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
3383 final String apkLib = "lib/";
3384 final int apkLibLen = apkLib.length();
3385 final int cpuAbiLen = cpuAbi.length();
3386 final String libPrefix = "lib";
3387 final int libPrefixLen = libPrefix.length();
3388 final String libSuffix = ".so";
3389 final int libSuffixLen = libSuffix.length();
3390 boolean hasNativeLibraries = false;
3391 boolean installedNativeLibraries = false;
3392
3393 // the minimum length of a valid native shared library of the form
3394 // lib/<something>/lib<name>.so.
3395 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
3396
3397 ZipFile zipFile = new ZipFile(scanFile);
3398 Enumeration<ZipEntry> entries =
3399 (Enumeration<ZipEntry>) zipFile.entries();
3400
3401 while (entries.hasMoreElements()) {
3402 ZipEntry entry = entries.nextElement();
3403 // skip directories
3404 if (entry.isDirectory()) {
3405 continue;
3406 }
3407 String entryName = entry.getName();
3408
3409 // check that the entry looks like lib/<something>/lib<name>.so
3410 // here, but don't check the ABI just yet.
3411 //
3412 // - must be sufficiently long
3413 // - must end with libSuffix, i.e. ".so"
3414 // - must start with apkLib, i.e. "lib/"
3415 if (entryName.length() < minEntryLen ||
3416 !entryName.endsWith(libSuffix) ||
3417 !entryName.startsWith(apkLib) ) {
3418 continue;
3419 }
3420
3421 // file name must start with libPrefix, i.e. "lib"
3422 int lastSlash = entryName.lastIndexOf('/');
3423
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003424 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003425 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
3426 continue;
3427 }
3428
3429 hasNativeLibraries = true;
3430
3431 // check the cpuAbi now, between lib/ and /lib<name>.so
3432 //
3433 if (lastSlash != apkLibLen + cpuAbiLen ||
3434 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3435 continue;
3436
3437 // extract the library file name, ensure it doesn't contain
3438 // weird characters. we're guaranteed here that it doesn't contain
3439 // a directory separator though.
3440 String libFileName = entryName.substring(lastSlash+1);
3441 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3442 continue;
3443 }
3444
3445 installedNativeLibraries = true;
3446
3447 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3448 File.separator + libFileName;
3449 File sharedLibraryFile = new File(sharedLibraryFilePath);
3450 if (! sharedLibraryFile.exists() ||
3451 sharedLibraryFile.length() != entry.getSize() ||
3452 sharedLibraryFile.lastModified() != entry.getTime()) {
3453 if (Config.LOGD) {
3454 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003456 if (mInstaller == null) {
3457 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003458 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003459 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003460 sharedLibraryFile);
3461 }
3462 }
3463 if (!hasNativeLibraries)
3464 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3465
3466 if (!installedNativeLibraries)
3467 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3468
3469 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3470 }
3471
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003472 // Find the gdbserver executable program in a package at
3473 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3474 //
3475 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3476 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3477 //
3478 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3479 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3480 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3481 final String GDBSERVER = "gdbserver";
3482 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3483
3484 ZipFile zipFile = new ZipFile(scanFile);
3485 Enumeration<ZipEntry> entries =
3486 (Enumeration<ZipEntry>) zipFile.entries();
3487
3488 while (entries.hasMoreElements()) {
3489 ZipEntry entry = entries.nextElement();
3490 // skip directories
3491 if (entry.isDirectory()) {
3492 continue;
3493 }
3494 String entryName = entry.getName();
3495
3496 if (!entryName.equals(apkGdbServerPath)) {
3497 continue;
3498 }
3499
3500 String installGdbServerPath = installGdbServerDir.getPath() +
3501 "/" + GDBSERVER;
3502 File installGdbServerFile = new File(installGdbServerPath);
3503 if (! installGdbServerFile.exists() ||
3504 installGdbServerFile.length() != entry.getSize() ||
3505 installGdbServerFile.lastModified() != entry.getTime()) {
3506 if (Config.LOGD) {
3507 Log.d(TAG, "Caching gdbserver " + entry.getName());
3508 }
3509 if (mInstaller == null) {
3510 installGdbServerDir.mkdir();
3511 }
3512 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3513 installGdbServerFile);
3514 }
3515 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3516 }
3517 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3518 }
3519
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003520 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3521 // and copy them to /data/data/<appname>/lib.
3522 //
3523 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3524 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3525 // one if ro.product.cpu.abi2 is defined.
3526 //
3527 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3528 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003529 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003530 try {
3531 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3532
3533 // some architectures are capable of supporting several CPU ABIs
3534 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3535 // this is indicated by the definition of the ro.product.cpu.abi2
3536 // system property.
3537 //
3538 // only scan the package twice in case of ABI mismatch
3539 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003540 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003541 if (cpuAbi2 != null) {
3542 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003543 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003544
3545 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3546 Log.w(TAG,"Native ABI mismatch from package file");
3547 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003549
3550 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3551 cpuAbi = cpuAbi2;
3552 }
3553 }
3554
3555 // for debuggable packages, also extract gdbserver from lib/<abi>
3556 // into /data/data/<appname>/lib too.
3557 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3558 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3559 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3560 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3561 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003564 } catch (ZipException e) {
3565 Log.w(TAG, "Failed to extract data from package file", e);
3566 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003568 Log.w(TAG, "Failed to cache package shared libs", e);
3569 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003571 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003572 }
3573
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003574 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003576 File binaryDir,
3577 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003578 InputStream inputStream = zipFile.getInputStream(entry);
3579 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003580 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003582 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 // now need to be left as world readable and owned by the system.
3584 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3585 ! tempFile.setLastModified(entry.getTime()) ||
3586 FileUtils.setPermissions(tempFilePath,
3587 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003588 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003590 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 // Failed to properly write file.
3592 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003593 throw new IOException("Couldn't create cached binary "
3594 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 }
3596 } finally {
3597 inputStream.close();
3598 }
3599 }
3600
3601 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3602 if (chatty && Config.LOGD) Log.d(
3603 TAG, "Removing package " + pkg.applicationInfo.packageName );
3604
3605 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003608 mPackages.remove(pkg.applicationInfo.packageName);
3609 if (pkg.mPath != null) {
3610 mAppDirs.remove(pkg.mPath);
3611 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003613 PackageSetting ps = (PackageSetting)pkg.mExtras;
3614 if (ps != null && ps.sharedUser != null) {
3615 // XXX don't do this until the data is removed.
3616 if (false) {
3617 ps.sharedUser.packages.remove(ps);
3618 if (ps.sharedUser.packages.size() == 0) {
3619 // Remove.
3620 }
3621 }
3622 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 int N = pkg.providers.size();
3625 StringBuilder r = null;
3626 int i;
3627 for (i=0; i<N; i++) {
3628 PackageParser.Provider p = pkg.providers.get(i);
3629 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3630 p.info.name));
3631 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003633 /* The is another ContentProvider with this authority when
3634 * this app was installed so this authority is null,
3635 * Ignore it as we don't have to unregister the provider.
3636 */
3637 continue;
3638 }
3639 String names[] = p.info.authority.split(";");
3640 for (int j = 0; j < names.length; j++) {
3641 if (mProviders.get(names[j]) == p) {
3642 mProviders.remove(names[j]);
3643 if (chatty && Config.LOGD) Log.d(
3644 TAG, "Unregistered content provider: " + names[j] +
3645 ", className = " + p.info.name +
3646 ", isSyncable = " + p.info.isSyncable);
3647 }
3648 }
3649 if (chatty) {
3650 if (r == null) {
3651 r = new StringBuilder(256);
3652 } else {
3653 r.append(' ');
3654 }
3655 r.append(p.info.name);
3656 }
3657 }
3658 if (r != null) {
3659 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3660 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 N = pkg.services.size();
3663 r = null;
3664 for (i=0; i<N; i++) {
3665 PackageParser.Service s = pkg.services.get(i);
3666 mServices.removeService(s);
3667 if (chatty) {
3668 if (r == null) {
3669 r = new StringBuilder(256);
3670 } else {
3671 r.append(' ');
3672 }
3673 r.append(s.info.name);
3674 }
3675 }
3676 if (r != null) {
3677 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3678 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 N = pkg.receivers.size();
3681 r = null;
3682 for (i=0; i<N; i++) {
3683 PackageParser.Activity a = pkg.receivers.get(i);
3684 mReceivers.removeActivity(a, "receiver");
3685 if (chatty) {
3686 if (r == null) {
3687 r = new StringBuilder(256);
3688 } else {
3689 r.append(' ');
3690 }
3691 r.append(a.info.name);
3692 }
3693 }
3694 if (r != null) {
3695 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 N = pkg.activities.size();
3699 r = null;
3700 for (i=0; i<N; i++) {
3701 PackageParser.Activity a = pkg.activities.get(i);
3702 mActivities.removeActivity(a, "activity");
3703 if (chatty) {
3704 if (r == null) {
3705 r = new StringBuilder(256);
3706 } else {
3707 r.append(' ');
3708 }
3709 r.append(a.info.name);
3710 }
3711 }
3712 if (r != null) {
3713 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3714 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 N = pkg.permissions.size();
3717 r = null;
3718 for (i=0; i<N; i++) {
3719 PackageParser.Permission p = pkg.permissions.get(i);
3720 boolean tree = false;
3721 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3722 if (bp == null) {
3723 tree = true;
3724 bp = mSettings.mPermissionTrees.get(p.info.name);
3725 }
3726 if (bp != null && bp.perm == p) {
3727 if (bp.type != BasePermission.TYPE_BUILTIN) {
3728 if (tree) {
3729 mSettings.mPermissionTrees.remove(p.info.name);
3730 } else {
3731 mSettings.mPermissions.remove(p.info.name);
3732 }
3733 } else {
3734 bp.perm = null;
3735 }
3736 if (chatty) {
3737 if (r == null) {
3738 r = new StringBuilder(256);
3739 } else {
3740 r.append(' ');
3741 }
3742 r.append(p.info.name);
3743 }
3744 }
3745 }
3746 if (r != null) {
3747 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3748 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 N = pkg.instrumentation.size();
3751 r = null;
3752 for (i=0; i<N; i++) {
3753 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003754 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003755 if (chatty) {
3756 if (r == null) {
3757 r = new StringBuilder(256);
3758 } else {
3759 r.append(' ');
3760 }
3761 r.append(a.info.name);
3762 }
3763 }
3764 if (r != null) {
3765 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3766 }
3767 }
3768 }
3769
3770 private static final boolean isPackageFilename(String name) {
3771 return name != null && name.endsWith(".apk");
3772 }
3773
3774 private void updatePermissionsLP() {
3775 // Make sure there are no dangling permission trees.
3776 Iterator<BasePermission> it = mSettings.mPermissionTrees
3777 .values().iterator();
3778 while (it.hasNext()) {
3779 BasePermission bp = it.next();
3780 if (bp.perm == null) {
3781 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3782 + " from package " + bp.sourcePackage);
3783 it.remove();
3784 }
3785 }
3786
3787 // Make sure all dynamic permissions have been assigned to a package,
3788 // and make sure there are no dangling permissions.
3789 it = mSettings.mPermissions.values().iterator();
3790 while (it.hasNext()) {
3791 BasePermission bp = it.next();
3792 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3793 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3794 + bp.name + " pkg=" + bp.sourcePackage
3795 + " info=" + bp.pendingInfo);
3796 if (bp.perm == null && bp.pendingInfo != null) {
3797 BasePermission tree = findPermissionTreeLP(bp.name);
3798 if (tree != null) {
3799 bp.perm = new PackageParser.Permission(tree.perm.owner,
3800 new PermissionInfo(bp.pendingInfo));
3801 bp.perm.info.packageName = tree.perm.info.packageName;
3802 bp.perm.info.name = bp.name;
3803 bp.uid = tree.uid;
3804 }
3805 }
3806 }
3807 if (bp.perm == null) {
3808 Log.w(TAG, "Removing dangling permission: " + bp.name
3809 + " from package " + bp.sourcePackage);
3810 it.remove();
3811 }
3812 }
3813
3814 // Now update the permissions for all packages, in particular
3815 // replace the granted permissions of the system packages.
3816 for (PackageParser.Package pkg : mPackages.values()) {
3817 grantPermissionsLP(pkg, false);
3818 }
3819 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3822 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3823 if (ps == null) {
3824 return;
3825 }
3826 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3827 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 if (replace) {
3830 ps.permissionsFixed = false;
3831 if (gp == ps) {
3832 gp.grantedPermissions.clear();
3833 gp.gids = mGlobalGids;
3834 }
3835 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 if (gp.gids == null) {
3838 gp.gids = mGlobalGids;
3839 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 final int N = pkg.requestedPermissions.size();
3842 for (int i=0; i<N; i++) {
3843 String name = pkg.requestedPermissions.get(i);
3844 BasePermission bp = mSettings.mPermissions.get(name);
3845 PackageParser.Permission p = bp != null ? bp.perm : null;
3846 if (false) {
3847 if (gp != ps) {
3848 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3849 + ": " + p);
3850 }
3851 }
3852 if (p != null) {
3853 final String perm = p.info.name;
3854 boolean allowed;
3855 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3856 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3857 allowed = true;
3858 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3859 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003860 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003862 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 == PackageManager.SIGNATURE_MATCH);
3864 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3865 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3866 // For updated system applications, the signatureOrSystem permission
3867 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003868 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3870 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3871 if(sysPs.grantedPermissions.contains(perm)) {
3872 allowed = true;
3873 } else {
3874 allowed = false;
3875 }
3876 } else {
3877 allowed = true;
3878 }
3879 }
3880 }
3881 } else {
3882 allowed = false;
3883 }
3884 if (false) {
3885 if (gp != ps) {
3886 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3887 }
3888 }
3889 if (allowed) {
3890 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3891 && ps.permissionsFixed) {
3892 // If this is an existing, non-system package, then
3893 // we can't add any new permissions to it.
3894 if (!gp.loadedPermissions.contains(perm)) {
3895 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003896 // Except... if this is a permission that was added
3897 // to the platform (note: need to only do this when
3898 // updating the platform).
3899 final int NP = PackageParser.NEW_PERMISSIONS.length;
3900 for (int ip=0; ip<NP; ip++) {
3901 final PackageParser.NewPermissionInfo npi
3902 = PackageParser.NEW_PERMISSIONS[ip];
3903 if (npi.name.equals(perm)
3904 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3905 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003906 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003907 + pkg.packageName);
3908 break;
3909 }
3910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003911 }
3912 }
3913 if (allowed) {
3914 if (!gp.grantedPermissions.contains(perm)) {
3915 addedPermission = true;
3916 gp.grantedPermissions.add(perm);
3917 gp.gids = appendInts(gp.gids, bp.gids);
3918 }
3919 } else {
3920 Log.w(TAG, "Not granting permission " + perm
3921 + " to package " + pkg.packageName
3922 + " because it was previously installed without");
3923 }
3924 } else {
3925 Log.w(TAG, "Not granting permission " + perm
3926 + " to package " + pkg.packageName
3927 + " (protectionLevel=" + p.info.protectionLevel
3928 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3929 + ")");
3930 }
3931 } else {
3932 Log.w(TAG, "Unknown permission " + name
3933 + " in package " + pkg.packageName);
3934 }
3935 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003938 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3939 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 // This is the first that we have heard about this package, so the
3941 // permissions we have now selected are fixed until explicitly
3942 // changed.
3943 ps.permissionsFixed = true;
3944 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3945 }
3946 }
3947
3948 private final class ActivityIntentResolver
3949 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003950 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003952 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 }
3954
Mihai Preda074edef2009-05-18 17:13:31 +02003955 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003957 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003958 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3959 }
3960
Mihai Predaeae850c2009-05-13 10:13:48 +02003961 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3962 ArrayList<PackageParser.Activity> packageActivities) {
3963 if (packageActivities == null) {
3964 return null;
3965 }
3966 mFlags = flags;
3967 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3968 int N = packageActivities.size();
3969 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3970 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003971
3972 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003973 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003974 intentFilters = packageActivities.get(i).intents;
3975 if (intentFilters != null && intentFilters.size() > 0) {
3976 listCut.add(intentFilters);
3977 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003978 }
3979 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3980 }
3981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003982 public final void addActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003983 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 if (SHOW_INFO || Config.LOGV) Log.v(
3985 TAG, " " + type + " " +
3986 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3987 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3988 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003989 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3991 if (SHOW_INFO || Config.LOGV) {
3992 Log.v(TAG, " IntentFilter:");
3993 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3994 }
3995 if (!intent.debugCheck()) {
3996 Log.w(TAG, "==> For Activity " + a.info.name);
3997 }
3998 addFilter(intent);
3999 }
4000 }
4001
4002 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004003 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 if (SHOW_INFO || Config.LOGV) Log.v(
4005 TAG, " " + type + " " +
4006 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4007 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4008 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004009 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
4011 if (SHOW_INFO || Config.LOGV) {
4012 Log.v(TAG, " IntentFilter:");
4013 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4014 }
4015 removeFilter(intent);
4016 }
4017 }
4018
4019 @Override
4020 protected boolean allowFilterResult(
4021 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4022 ActivityInfo filterAi = filter.activity.info;
4023 for (int i=dest.size()-1; i>=0; i--) {
4024 ActivityInfo destAi = dest.get(i).activityInfo;
4025 if (destAi.name == filterAi.name
4026 && destAi.packageName == filterAi.packageName) {
4027 return false;
4028 }
4029 }
4030 return true;
4031 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 @Override
4034 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
4035 int match) {
4036 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
4037 return null;
4038 }
4039 final PackageParser.Activity activity = info.activity;
4040 if (mSafeMode && (activity.info.applicationInfo.flags
4041 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4042 return null;
4043 }
4044 final ResolveInfo res = new ResolveInfo();
4045 res.activityInfo = PackageParser.generateActivityInfo(activity,
4046 mFlags);
4047 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4048 res.filter = info;
4049 }
4050 res.priority = info.getPriority();
4051 res.preferredOrder = activity.owner.mPreferredOrder;
4052 //System.out.println("Result: " + res.activityInfo.className +
4053 // " = " + res.priority);
4054 res.match = match;
4055 res.isDefault = info.hasDefault;
4056 res.labelRes = info.labelRes;
4057 res.nonLocalizedLabel = info.nonLocalizedLabel;
4058 res.icon = info.icon;
4059 return res;
4060 }
4061
4062 @Override
4063 protected void sortResults(List<ResolveInfo> results) {
4064 Collections.sort(results, mResolvePrioritySorter);
4065 }
4066
4067 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004068 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004069 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004070 out.print(prefix); out.print(
4071 Integer.toHexString(System.identityHashCode(filter.activity)));
4072 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004073 out.println(filter.activity.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004074 }
4075
4076// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4077// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4078// final List<ResolveInfo> retList = Lists.newArrayList();
4079// while (i.hasNext()) {
4080// final ResolveInfo resolveInfo = i.next();
4081// if (isEnabledLP(resolveInfo.activityInfo)) {
4082// retList.add(resolveInfo);
4083// }
4084// }
4085// return retList;
4086// }
4087
4088 // Keys are String (activity class name), values are Activity.
4089 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4090 = new HashMap<ComponentName, PackageParser.Activity>();
4091 private int mFlags;
4092 }
4093
4094 private final class ServiceIntentResolver
4095 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02004096 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004098 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 }
4100
Mihai Preda074edef2009-05-18 17:13:31 +02004101 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004103 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4105 }
4106
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07004107 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4108 ArrayList<PackageParser.Service> packageServices) {
4109 if (packageServices == null) {
4110 return null;
4111 }
4112 mFlags = flags;
4113 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4114 int N = packageServices.size();
4115 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4116 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4117
4118 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4119 for (int i = 0; i < N; ++i) {
4120 intentFilters = packageServices.get(i).intents;
4121 if (intentFilters != null && intentFilters.size() > 0) {
4122 listCut.add(intentFilters);
4123 }
4124 }
4125 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4126 }
4127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004129 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 if (SHOW_INFO || Config.LOGV) Log.v(
4131 TAG, " " + (s.info.nonLocalizedLabel != null
4132 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4133 if (SHOW_INFO || Config.LOGV) Log.v(
4134 TAG, " Class=" + s.info.name);
4135 int NI = s.intents.size();
4136 int j;
4137 for (j=0; j<NI; j++) {
4138 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4139 if (SHOW_INFO || Config.LOGV) {
4140 Log.v(TAG, " IntentFilter:");
4141 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4142 }
4143 if (!intent.debugCheck()) {
4144 Log.w(TAG, "==> For Service " + s.info.name);
4145 }
4146 addFilter(intent);
4147 }
4148 }
4149
4150 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004151 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 if (SHOW_INFO || Config.LOGV) Log.v(
4153 TAG, " " + (s.info.nonLocalizedLabel != null
4154 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4155 if (SHOW_INFO || Config.LOGV) Log.v(
4156 TAG, " Class=" + s.info.name);
4157 int NI = s.intents.size();
4158 int j;
4159 for (j=0; j<NI; j++) {
4160 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4161 if (SHOW_INFO || Config.LOGV) {
4162 Log.v(TAG, " IntentFilter:");
4163 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4164 }
4165 removeFilter(intent);
4166 }
4167 }
4168
4169 @Override
4170 protected boolean allowFilterResult(
4171 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4172 ServiceInfo filterSi = filter.service.info;
4173 for (int i=dest.size()-1; i>=0; i--) {
4174 ServiceInfo destAi = dest.get(i).serviceInfo;
4175 if (destAi.name == filterSi.name
4176 && destAi.packageName == filterSi.packageName) {
4177 return false;
4178 }
4179 }
4180 return true;
4181 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183 @Override
4184 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4185 int match) {
4186 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
4187 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4188 return null;
4189 }
4190 final PackageParser.Service service = info.service;
4191 if (mSafeMode && (service.info.applicationInfo.flags
4192 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4193 return null;
4194 }
4195 final ResolveInfo res = new ResolveInfo();
4196 res.serviceInfo = PackageParser.generateServiceInfo(service,
4197 mFlags);
4198 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4199 res.filter = filter;
4200 }
4201 res.priority = info.getPriority();
4202 res.preferredOrder = service.owner.mPreferredOrder;
4203 //System.out.println("Result: " + res.activityInfo.className +
4204 // " = " + res.priority);
4205 res.match = match;
4206 res.isDefault = info.hasDefault;
4207 res.labelRes = info.labelRes;
4208 res.nonLocalizedLabel = info.nonLocalizedLabel;
4209 res.icon = info.icon;
4210 return res;
4211 }
4212
4213 @Override
4214 protected void sortResults(List<ResolveInfo> results) {
4215 Collections.sort(results, mResolvePrioritySorter);
4216 }
4217
4218 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004219 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004221 out.print(prefix); out.print(
4222 Integer.toHexString(System.identityHashCode(filter.service)));
4223 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004224 out.println(filter.service.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 }
4226
4227// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4228// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4229// final List<ResolveInfo> retList = Lists.newArrayList();
4230// while (i.hasNext()) {
4231// final ResolveInfo resolveInfo = (ResolveInfo) i;
4232// if (isEnabledLP(resolveInfo.serviceInfo)) {
4233// retList.add(resolveInfo);
4234// }
4235// }
4236// return retList;
4237// }
4238
4239 // Keys are String (activity class name), values are Activity.
4240 private final HashMap<ComponentName, PackageParser.Service> mServices
4241 = new HashMap<ComponentName, PackageParser.Service>();
4242 private int mFlags;
4243 };
4244
4245 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4246 new Comparator<ResolveInfo>() {
4247 public int compare(ResolveInfo r1, ResolveInfo r2) {
4248 int v1 = r1.priority;
4249 int v2 = r2.priority;
4250 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4251 if (v1 != v2) {
4252 return (v1 > v2) ? -1 : 1;
4253 }
4254 v1 = r1.preferredOrder;
4255 v2 = r2.preferredOrder;
4256 if (v1 != v2) {
4257 return (v1 > v2) ? -1 : 1;
4258 }
4259 if (r1.isDefault != r2.isDefault) {
4260 return r1.isDefault ? -1 : 1;
4261 }
4262 v1 = r1.match;
4263 v2 = r2.match;
4264 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4265 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4266 }
4267 };
4268
4269 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4270 new Comparator<ProviderInfo>() {
4271 public int compare(ProviderInfo p1, ProviderInfo p2) {
4272 final int v1 = p1.initOrder;
4273 final int v2 = p2.initOrder;
4274 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4275 }
4276 };
4277
4278 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
4279 IActivityManager am = ActivityManagerNative.getDefault();
4280 if (am != null) {
4281 try {
4282 final Intent intent = new Intent(action,
4283 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4284 if (extras != null) {
4285 intent.putExtras(extras);
4286 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004287 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 am.broadcastIntent(
4289 null, intent,
4290 null, null, 0, null, null, null, false, false);
4291 } catch (RemoteException ex) {
4292 }
4293 }
4294 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004295
4296 public String nextPackageToClean(String lastPackage) {
4297 synchronized (mPackages) {
4298 if (!mMediaMounted) {
4299 // If the external storage is no longer mounted at this point,
4300 // the caller may not have been able to delete all of this
4301 // packages files and can not delete any more. Bail.
4302 return null;
4303 }
4304 if (lastPackage != null) {
4305 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4306 }
4307 return mSettings.mPackagesToBeCleaned.size() > 0
4308 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4309 }
4310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004312 void schedulePackageCleaning(String packageName) {
4313 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4314 }
4315
4316 void startCleaningPackages() {
4317 synchronized (mPackages) {
4318 if (!mMediaMounted) {
4319 return;
4320 }
4321 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4322 return;
4323 }
4324 }
4325 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4326 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4327 IActivityManager am = ActivityManagerNative.getDefault();
4328 if (am != null) {
4329 try {
4330 am.startService(null, intent, null);
4331 } catch (RemoteException e) {
4332 }
4333 }
4334 }
4335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 private final class AppDirObserver extends FileObserver {
4337 public AppDirObserver(String path, int mask, boolean isrom) {
4338 super(path, mask);
4339 mRootDir = path;
4340 mIsRom = isrom;
4341 }
4342
4343 public void onEvent(int event, String path) {
4344 String removedPackage = null;
4345 int removedUid = -1;
4346 String addedPackage = null;
4347 int addedUid = -1;
4348
4349 synchronized (mInstallLock) {
4350 String fullPathStr = null;
4351 File fullPath = null;
4352 if (path != null) {
4353 fullPath = new File(mRootDir, path);
4354 fullPathStr = fullPath.getPath();
4355 }
4356
4357 if (Config.LOGV) Log.v(
4358 TAG, "File " + fullPathStr + " changed: "
4359 + Integer.toHexString(event));
4360
4361 if (!isPackageFilename(path)) {
4362 if (Config.LOGV) Log.v(
4363 TAG, "Ignoring change of non-package file: " + fullPathStr);
4364 return;
4365 }
4366
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004367 // Ignore packages that are being installed or
4368 // have just been installed.
4369 if (ignoreCodePath(fullPathStr)) {
4370 return;
4371 }
4372 PackageParser.Package p = null;
4373 synchronized (mPackages) {
4374 p = mAppDirs.get(fullPathStr);
4375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004377 if (p != null) {
4378 removePackageLI(p, true);
4379 removedPackage = p.applicationInfo.packageName;
4380 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 }
4382 }
4383
4384 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004386 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004387 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
4388 PackageParser.PARSE_CHATTY |
4389 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08004390 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 if (p != null) {
4392 synchronized (mPackages) {
4393 grantPermissionsLP(p, false);
4394 }
4395 addedPackage = p.applicationInfo.packageName;
4396 addedUid = p.applicationInfo.uid;
4397 }
4398 }
4399 }
4400
4401 synchronized (mPackages) {
4402 mSettings.writeLP();
4403 }
4404 }
4405
4406 if (removedPackage != null) {
4407 Bundle extras = new Bundle(1);
4408 extras.putInt(Intent.EXTRA_UID, removedUid);
4409 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4410 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4411 }
4412 if (addedPackage != null) {
4413 Bundle extras = new Bundle(1);
4414 extras.putInt(Intent.EXTRA_UID, addedUid);
4415 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
4416 }
4417 }
4418
4419 private final String mRootDir;
4420 private final boolean mIsRom;
4421 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 /* Called when a downloaded package installation has been confirmed by the user */
4424 public void installPackage(
4425 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004426 installPackage(packageURI, observer, flags, null);
4427 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004428
Jacek Surazski65e13172009-04-28 15:26:38 +02004429 /* Called when a downloaded package installation has been confirmed by the user */
4430 public void installPackage(
4431 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4432 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 mContext.enforceCallingOrSelfPermission(
4434 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004435
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004436 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004437 msg.obj = new InstallParams(packageURI, observer, flags,
4438 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004439 mHandler.sendMessage(msg);
4440 }
4441
Christopher Tate1bb69062010-02-19 17:02:12 -08004442 public void finishPackageInstall(int token) {
4443 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4444 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4445 mHandler.sendMessage(msg);
4446 }
4447
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004448 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 // Queue up an async operation since the package installation may take a little while.
4450 mHandler.post(new Runnable() {
4451 public void run() {
4452 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004453 // Result object to be returned
4454 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004455 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004456 res.uid = -1;
4457 res.pkg = null;
4458 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004459 args.doPreInstall(res.returnCode);
4460 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004461 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004462 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004463 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004464 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004466
4467 // A restore should be performed at this point if (a) the install
4468 // succeeded, (b) the operation is not an update, and (c) the new
4469 // package has a backupAgent defined.
4470 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004471 boolean doRestore = (!update
4472 && res.pkg != null
4473 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004474
4475 // Set up the post-install work request bookkeeping. This will be used
4476 // and cleaned up by the post-install event handling regardless of whether
4477 // there's a restore pass performed. Token values are >= 1.
4478 int token;
4479 if (mNextInstallToken < 0) mNextInstallToken = 1;
4480 token = mNextInstallToken++;
4481
4482 PostInstallData data = new PostInstallData(args, res);
4483 mRunningInstalls.put(token, data);
4484 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4485
4486 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4487 // Pass responsibility to the Backup Manager. It will perform a
4488 // restore if appropriate, then pass responsibility back to the
4489 // Package Manager to run the post-install observer callbacks
4490 // and broadcasts.
4491 IBackupManager bm = IBackupManager.Stub.asInterface(
4492 ServiceManager.getService(Context.BACKUP_SERVICE));
4493 if (bm != null) {
4494 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4495 + " to BM for possible restore");
4496 try {
4497 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4498 } catch (RemoteException e) {
4499 // can't happen; the backup manager is local
4500 } catch (Exception e) {
4501 Log.e(TAG, "Exception trying to enqueue restore", e);
4502 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004503 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004504 } else {
4505 Log.e(TAG, "Backup Manager not found!");
4506 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004509
4510 if (!doRestore) {
4511 // No restore possible, or the Backup Manager was mysteriously not
4512 // available -- just fire the post-install work request directly.
4513 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4514 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4515 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004517 }
4518 });
4519 }
4520
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004521 abstract class HandlerParams {
4522 final static int MAX_RETRIES = 4;
4523 int retry = 0;
4524 final void startCopy() {
4525 try {
4526 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
4527 retry++;
4528 if (retry > MAX_RETRIES) {
4529 Log.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
4530 mHandler.sendEmptyMessage(MCS_GIVE_UP);
4531 handleServiceError();
4532 return;
4533 } else {
4534 handleStartCopy();
4535 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
4536 mHandler.sendEmptyMessage(MCS_UNBIND);
4537 }
4538 } catch (RemoteException e) {
4539 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
4540 mHandler.sendEmptyMessage(MCS_RECONNECT);
4541 }
4542 handleReturnCode();
4543 }
4544
4545 final void serviceError() {
4546 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
4547 handleServiceError();
4548 handleReturnCode();
4549 }
4550 abstract void handleStartCopy() throws RemoteException;
4551 abstract void handleServiceError();
4552 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004553 }
4554
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004555 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004556 final IPackageInstallObserver observer;
4557 int flags;
4558 final Uri packageURI;
4559 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004560 private InstallArgs mArgs;
4561 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004562 InstallParams(Uri packageURI,
4563 IPackageInstallObserver observer, int flags,
4564 String installerPackageName) {
4565 this.packageURI = packageURI;
4566 this.flags = flags;
4567 this.observer = observer;
4568 this.installerPackageName = installerPackageName;
4569 }
4570
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004571 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004572 int ret = PackageManager.INSTALL_SUCCEEDED;
4573 // Dont need to invoke getInstallLocation for forward locked apps.
4574 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4575 flags &= ~PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004576 } else {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004577 // Remote call to find out default install location
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004578 int loc = mContainerService.getRecommendedInstallLocation(packageURI);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004579 // Use install location to create InstallArgs and temporary
4580 // install location
4581 if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
4582 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4583 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
4584 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
4585 } else {
4586 if ((flags & PackageManager.INSTALL_EXTERNAL) == 0){
4587 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
4588 // Set the flag to install on external media.
4589 flags |= PackageManager.INSTALL_EXTERNAL;
4590 } else {
4591 // Make sure the flag for installing on external
4592 // media is unset
4593 flags &= ~PackageManager.INSTALL_EXTERNAL;
4594 }
4595 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004596 }
4597 }
4598 // Create the file args now.
4599 mArgs = createInstallArgs(this);
4600 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4601 // Create copy only if we are not in an erroneous state.
4602 // Remote call to initiate copy using temporary file
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004603 ret = mArgs.copyApk(mContainerService, true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004604 }
4605 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004606 }
4607
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004608 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004609 void handleReturnCode() {
4610 processPendingInstall(mArgs, mRet);
4611 }
4612
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004613 @Override
4614 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004615 mArgs = createInstallArgs(this);
4616 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004617 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004618 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004619
4620 /*
4621 * Utility class used in movePackage api.
4622 * srcArgs and targetArgs are not set for invalid flags and make
4623 * sure to do null checks when invoking methods on them.
4624 * We probably want to return ErrorPrams for both failed installs
4625 * and moves.
4626 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004627 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004628 final IPackageMoveObserver observer;
4629 final int flags;
4630 final String packageName;
4631 final InstallArgs srcArgs;
4632 final InstallArgs targetArgs;
4633 int mRet;
4634 MoveParams(InstallArgs srcArgs,
4635 IPackageMoveObserver observer,
4636 int flags, String packageName) {
4637 this.srcArgs = srcArgs;
4638 this.observer = observer;
4639 this.flags = flags;
4640 this.packageName = packageName;
4641 if (srcArgs != null) {
4642 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
4643 targetArgs = createInstallArgs(packageUri, flags, packageName);
4644 } else {
4645 targetArgs = null;
4646 }
4647 }
4648
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004649 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004650 // Create the file args now.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004651 mRet = targetArgs.copyApk(mContainerService, false);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004652 targetArgs.doPreInstall(mRet);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004653 if (DEBUG_SD_INSTALL) {
4654 StringBuilder builder = new StringBuilder();
4655 if (srcArgs != null) {
4656 builder.append("src: ");
4657 builder.append(srcArgs.getCodePath());
4658 }
4659 if (targetArgs != null) {
4660 builder.append(" target : ");
4661 builder.append(targetArgs.getCodePath());
4662 }
4663 Log.i(TAG, "Posting move MCS_UNBIND for " + builder.toString());
4664 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004665 }
4666
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004667 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004668 void handleReturnCode() {
4669 targetArgs.doPostInstall(mRet);
4670 // TODO invoke pending move
4671 processPendingMove(this, mRet);
4672 }
4673
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004674 @Override
4675 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004676 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004677 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004678 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004679
4680 private InstallArgs createInstallArgs(InstallParams params) {
4681 if (installOnSd(params.flags)) {
4682 return new SdInstallArgs(params);
4683 } else {
4684 return new FileInstallArgs(params);
4685 }
4686 }
4687
4688 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
4689 if (installOnSd(flags)) {
4690 return new SdInstallArgs(fullCodePath, fullResourcePath);
4691 } else {
4692 return new FileInstallArgs(fullCodePath, fullResourcePath);
4693 }
4694 }
4695
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004696 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName) {
4697 if (installOnSd(flags)) {
4698 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
4699 return new SdInstallArgs(packageURI, cid);
4700 } else {
4701 return new FileInstallArgs(packageURI, pkgName);
4702 }
4703 }
4704
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004705 static abstract class InstallArgs {
4706 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004707 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004708 final int flags;
4709 final Uri packageURI;
4710 final String installerPackageName;
4711
4712 InstallArgs(Uri packageURI,
4713 IPackageInstallObserver observer, int flags,
4714 String installerPackageName) {
4715 this.packageURI = packageURI;
4716 this.flags = flags;
4717 this.observer = observer;
4718 this.installerPackageName = installerPackageName;
4719 }
4720
4721 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004722 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004723 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004724 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004725 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004726 abstract String getCodePath();
4727 abstract String getResourcePath();
4728 // Need installer lock especially for dex file removal.
4729 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004730 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004731 }
4732
4733 class FileInstallArgs extends InstallArgs {
4734 File installDir;
4735 String codeFileName;
4736 String resourceFileName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004737 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004738
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004739 FileInstallArgs(InstallParams params) {
4740 super(params.packageURI, params.observer,
4741 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004742 }
4743
4744 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4745 super(null, null, 0, null);
4746 File codeFile = new File(fullCodePath);
4747 installDir = codeFile.getParentFile();
4748 codeFileName = fullCodePath;
4749 resourceFileName = fullResourcePath;
4750 }
4751
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004752 FileInstallArgs(Uri packageURI, String pkgName) {
4753 super(packageURI, null, 0, null);
4754 boolean fwdLocked = isFwdLocked(flags);
4755 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4756 String apkName = getNextCodePath(null, pkgName, ".apk");
4757 codeFileName = new File(installDir, apkName + ".apk").getPath();
4758 resourceFileName = getResourcePathFromCodePath();
4759 }
4760
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004761 String getCodePath() {
4762 return codeFileName;
4763 }
4764
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004765 void createCopyFile() {
4766 boolean fwdLocked = isFwdLocked(flags);
4767 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4768 codeFileName = createTempPackageFile(installDir).getPath();
4769 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004770 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004771 }
4772
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004773 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004774 if (temp) {
4775 // Generate temp file name
4776 createCopyFile();
4777 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004778 // Get a ParcelFileDescriptor to write to the output file
4779 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004780 if (!created) {
4781 try {
4782 codeFile.createNewFile();
4783 // Set permissions
4784 if (!setPermissions()) {
4785 // Failed setting permissions.
4786 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4787 }
4788 } catch (IOException e) {
4789 Log.w(TAG, "Failed to create file " + codeFile);
4790 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4791 }
4792 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004793 ParcelFileDescriptor out = null;
4794 try {
4795 out = ParcelFileDescriptor.open(codeFile,
4796 ParcelFileDescriptor.MODE_READ_WRITE);
4797 } catch (FileNotFoundException e) {
4798 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4799 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4800 }
4801 // Copy the resource now
4802 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4803 try {
4804 if (imcs.copyResource(packageURI, out)) {
4805 ret = PackageManager.INSTALL_SUCCEEDED;
4806 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004807 } finally {
4808 try { if (out != null) out.close(); } catch (IOException e) {}
4809 }
4810 return ret;
4811 }
4812
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004813 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004814 if (status != PackageManager.INSTALL_SUCCEEDED) {
4815 cleanUp();
4816 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004817 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004818 }
4819
4820 boolean doRename(int status, final String pkgName, String oldCodePath) {
4821 if (status != PackageManager.INSTALL_SUCCEEDED) {
4822 cleanUp();
4823 return false;
4824 } else {
4825 // Rename based on packageName
4826 File codeFile = new File(getCodePath());
4827 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4828 File desFile = new File(installDir, apkName + ".apk");
4829 if (!codeFile.renameTo(desFile)) {
4830 return false;
4831 }
4832 // Reset paths since the file has been renamed.
4833 codeFileName = desFile.getPath();
4834 resourceFileName = getResourcePathFromCodePath();
4835 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004836 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004837 // Failed setting permissions.
4838 return false;
4839 }
4840 return true;
4841 }
4842 }
4843
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004844 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004845 if (status != PackageManager.INSTALL_SUCCEEDED) {
4846 cleanUp();
4847 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004848 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004849 }
4850
4851 String getResourcePath() {
4852 return resourceFileName;
4853 }
4854
4855 String getResourcePathFromCodePath() {
4856 String codePath = getCodePath();
4857 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4858 String apkNameOnly = getApkName(codePath);
4859 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4860 } else {
4861 return codePath;
4862 }
4863 }
4864
4865 private boolean cleanUp() {
4866 boolean ret = true;
4867 String sourceDir = getCodePath();
4868 String publicSourceDir = getResourcePath();
4869 if (sourceDir != null) {
4870 File sourceFile = new File(sourceDir);
4871 if (!sourceFile.exists()) {
4872 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4873 ret = false;
4874 }
4875 // Delete application's code and resources
4876 sourceFile.delete();
4877 }
4878 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4879 final File publicSourceFile = new File(publicSourceDir);
4880 if (!publicSourceFile.exists()) {
4881 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4882 }
4883 if (publicSourceFile.exists()) {
4884 publicSourceFile.delete();
4885 }
4886 }
4887 return ret;
4888 }
4889
4890 void cleanUpResourcesLI() {
4891 String sourceDir = getCodePath();
4892 if (cleanUp() && mInstaller != null) {
4893 int retCode = mInstaller.rmdex(sourceDir);
4894 if (retCode < 0) {
4895 Log.w(TAG, "Couldn't remove dex file for package: "
4896 + " at location "
4897 + sourceDir + ", retcode=" + retCode);
4898 // we don't consider this to be a failure of the core package deletion
4899 }
4900 }
4901 }
4902
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004903 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004904 // TODO Do this in a more elegant way later on. for now just a hack
4905 if (!isFwdLocked(flags)) {
4906 final int filePermissions =
4907 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4908 |FileUtils.S_IROTH;
4909 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4910 if (retCode != 0) {
4911 Log.e(TAG, "Couldn't set new package file permissions for " +
4912 getCodePath()
4913 + ". The return code was: " + retCode);
4914 // TODO Define new internal error
4915 return false;
4916 }
4917 return true;
4918 }
4919 return true;
4920 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004921
4922 boolean doPostDeleteLI(boolean delete) {
4923 cleanUpResourcesLI();
4924 return true;
4925 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004926 }
4927
4928 class SdInstallArgs extends InstallArgs {
4929 String cid;
4930 String cachePath;
4931 static final String RES_FILE_NAME = "pkg.apk";
4932
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004933 SdInstallArgs(InstallParams params) {
4934 super(params.packageURI, params.observer,
4935 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004936 }
4937
4938 SdInstallArgs(String fullCodePath, String fullResourcePath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004939 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004940 // Extract cid from fullCodePath
4941 int eidx = fullCodePath.lastIndexOf("/");
4942 String subStr1 = fullCodePath.substring(0, eidx);
4943 int sidx = subStr1.lastIndexOf("/");
4944 cid = subStr1.substring(sidx+1, eidx);
4945 cachePath = subStr1;
4946 }
4947
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004948 SdInstallArgs(String cid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004949 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
4950 this.cid = cid;
4951 }
4952
4953 SdInstallArgs(Uri packageURI, String cid) {
4954 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004955 this.cid = cid;
4956 }
4957
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004958 void createCopyFile() {
4959 cid = getTempContainerId();
4960 }
4961
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004962 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004963 if (temp) {
4964 createCopyFile();
4965 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004966 cachePath = imcs.copyResourceToContainer(
4967 packageURI, cid,
4968 getEncryptKey(), RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004969 return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
4970 PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004971 }
4972
4973 @Override
4974 String getCodePath() {
4975 return cachePath + "/" + RES_FILE_NAME;
4976 }
4977
4978 @Override
4979 String getResourcePath() {
4980 return cachePath + "/" + RES_FILE_NAME;
4981 }
4982
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004983 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004984 if (status != PackageManager.INSTALL_SUCCEEDED) {
4985 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004986 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004987 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004988 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004989 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004990 cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004991 if (cachePath == null) {
4992 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4993 }
4994 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004995 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004996 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004997 }
4998
4999 boolean doRename(int status, final String pkgName,
5000 String oldCodePath) {
5001 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005002 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005003 if (PackageHelper.isContainerMounted(cid)) {
5004 // Unmount the container
5005 if (!PackageHelper.unMountSdDir(cid)) {
5006 Log.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005007 return false;
5008 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005009 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005010 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
5011 Log.e(TAG, "Failed to rename " + cid + " to " + newCacheId);
5012 return false;
5013 }
5014 if (!PackageHelper.isContainerMounted(newCacheId)) {
5015 Log.w(TAG, "Mounting container " + newCacheId);
5016 newCachePath = PackageHelper.mountSdDir(newCacheId,
5017 getEncryptKey(), Process.SYSTEM_UID);
5018 } else {
5019 newCachePath = PackageHelper.getSdDir(newCacheId);
5020 }
5021 if (newCachePath == null) {
5022 Log.w(TAG, "Failed to get cache path for " + newCacheId);
5023 return false;
5024 }
5025 Log.i(TAG, "Succesfully renamed " + cid +
5026 " at path: " + cachePath + " to " + newCacheId +
5027 " at new path: " + newCachePath);
5028 cid = newCacheId;
5029 cachePath = newCachePath;
5030 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005031 }
5032
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005033 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005034 if (status != PackageManager.INSTALL_SUCCEEDED) {
5035 cleanUp();
5036 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005037 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005038 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005039 PackageHelper.mountSdDir(cid,
5040 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005041 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005042 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005043 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005044 }
5045
5046 private void cleanUp() {
5047 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005048 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005049 }
5050
5051 void cleanUpResourcesLI() {
5052 String sourceFile = getCodePath();
5053 // Remove dex file
5054 if (mInstaller != null) {
5055 int retCode = mInstaller.rmdex(sourceFile.toString());
5056 if (retCode < 0) {
5057 Log.w(TAG, "Couldn't remove dex file for package: "
5058 + " at location "
5059 + sourceFile.toString() + ", retcode=" + retCode);
5060 // we don't consider this to be a failure of the core package deletion
5061 }
5062 }
5063 cleanUp();
5064 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005065
5066 boolean matchContainer(String app) {
5067 if (cid.startsWith(app)) {
5068 return true;
5069 }
5070 return false;
5071 }
5072
5073 String getPackageName() {
5074 int idx = cid.lastIndexOf("-");
5075 if (idx == -1) {
5076 return cid;
5077 }
5078 return cid.substring(0, idx);
5079 }
5080
5081 boolean doPostDeleteLI(boolean delete) {
5082 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005083 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005084 if (mounted) {
5085 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005086 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005087 }
5088 if (ret && delete) {
5089 cleanUpResourcesLI();
5090 }
5091 return ret;
5092 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005093 };
5094
5095 // Utility method used to create code paths based on package name and available index.
5096 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
5097 String idxStr = "";
5098 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005099 // Fall back to default value of idx=1 if prefix is not
5100 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005101 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005102 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005103 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005104 if (subStr.endsWith(suffix)) {
5105 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005106 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005107 // If oldCodePath already contains prefix find out the
5108 // ending index to either increment or decrement.
5109 int sidx = subStr.lastIndexOf(prefix);
5110 if (sidx != -1) {
5111 subStr = subStr.substring(sidx + prefix.length());
5112 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005113 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5114 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005115 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005116 try {
5117 idx = Integer.parseInt(subStr);
5118 if (idx <= 1) {
5119 idx++;
5120 } else {
5121 idx--;
5122 }
5123 } catch(NumberFormatException e) {
5124 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005125 }
5126 }
5127 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005128 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005129 return prefix + idxStr;
5130 }
5131
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005132 // Utility method used to ignore ADD/REMOVE events
5133 // by directory observer.
5134 private static boolean ignoreCodePath(String fullPathStr) {
5135 String apkName = getApkName(fullPathStr);
5136 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5137 if (idx != -1 && ((idx+1) < apkName.length())) {
5138 // Make sure the package ends with a numeral
5139 String version = apkName.substring(idx+1);
5140 try {
5141 Integer.parseInt(version);
5142 return true;
5143 } catch (NumberFormatException e) {}
5144 }
5145 return false;
5146 }
5147
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005148 // Utility method that returns the relative package path with respect
5149 // to the installation directory. Like say for /data/data/com.test-1.apk
5150 // string com.test-1 is returned.
5151 static String getApkName(String codePath) {
5152 if (codePath == null) {
5153 return null;
5154 }
5155 int sidx = codePath.lastIndexOf("/");
5156 int eidx = codePath.lastIndexOf(".");
5157 if (eidx == -1) {
5158 eidx = codePath.length();
5159 } else if (eidx == 0) {
5160 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
5161 return null;
5162 }
5163 return codePath.substring(sidx+1, eidx);
5164 }
5165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 class PackageInstalledInfo {
5167 String name;
5168 int uid;
5169 PackageParser.Package pkg;
5170 int returnCode;
5171 PackageRemovedInfo removedInfo;
5172 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 /*
5175 * Install a non-existing package.
5176 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005177 private void installNewPackageLI(PackageParser.Package pkg,
5178 int parseFlags,
5179 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005180 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005182 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005183
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08005184 boolean dataDirExists = getDataPathForPackage(pkg).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005185 res.name = pkgName;
5186 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005187 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005188 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005189 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005190 + " without first uninstalling.");
5191 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5192 return;
5193 }
5194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005196 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005198 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5200 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5201 }
5202 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005203 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005204 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 res);
5206 // delete the partially installed application. the data directory will have to be
5207 // restored if it was already existing
5208 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5209 // remove package from internal structures. Note that we want deletePackageX to
5210 // delete the package data and cache directories that it created in
5211 // scanPackageLocked, unless those directories existed before we even tried to
5212 // install.
5213 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005214 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005215 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
5216 res.removedInfo);
5217 }
5218 }
5219 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005220
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005221 private void replacePackageLI(PackageParser.Package pkg,
5222 int parseFlags,
5223 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005224 String installerPackageName, PackageInstalledInfo res) {
5225
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005226 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005227 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 // First find the old package info and check signatures
5229 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005230 oldPackage = mPackages.get(pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005231 if (checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005232 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5234 return;
5235 }
5236 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005237 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005238 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005239 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005241 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 }
5243 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005245 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005246 PackageParser.Package pkg,
5247 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005248 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 PackageParser.Package newPackage = null;
5250 String pkgName = deletedPackage.packageName;
5251 boolean deletedPkg = true;
5252 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005253
Jacek Surazski65e13172009-04-28 15:26:38 +02005254 String oldInstallerPackageName = null;
5255 synchronized (mPackages) {
5256 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
5257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005258
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005259 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005261 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005262 res.removedInfo)) {
5263 // If the existing package was'nt successfully deleted
5264 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5265 deletedPkg = false;
5266 } else {
5267 // Successfully deleted the old package. Now proceed with re-installation
5268 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005269 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005271 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5273 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005274 }
5275 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005276 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005277 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 res);
5279 updatedSettings = true;
5280 }
5281 }
5282
5283 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5284 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005285 // were keeping around in case we needed them (see below) can now be deleted.
5286 // This info will be set on the res.removedInfo to clean up later on as post
5287 // install action.
5288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 //update signature on the new package setting
5290 //this should always succeed, since we checked the
5291 //signature earlier.
5292 synchronized(mPackages) {
5293 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
5294 parseFlags, true);
5295 }
5296 } else {
5297 // remove package from internal structures. Note that we want deletePackageX to
5298 // delete the package data and cache directories that it created in
5299 // scanPackageLocked, unless those directories existed before we even tried to
5300 // install.
5301 if(updatedSettings) {
5302 deletePackageLI(
5303 pkgName, true,
5304 PackageManager.DONT_DELETE_DATA,
5305 res.removedInfo);
5306 }
5307 // Since we failed to install the new package we need to restore the old
5308 // package that we deleted.
5309 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005310 File restoreFile = new File(deletedPackage.mPath);
5311 if (restoreFile == null) {
5312 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
5313 return;
5314 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005315 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
5316 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005317 // Parse old package
5318 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
5319 scanPackageLI(restoreFile, parseFlags, scanMode);
5320 synchronized (mPackages) {
5321 grantPermissionsLP(deletedPackage, false);
5322 mSettings.writeLP();
5323 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005324 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5325 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
5326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005327 }
5328 }
5329 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005332 PackageParser.Package pkg,
5333 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005334 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 PackageParser.Package newPackage = null;
5336 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005337 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 PackageParser.PARSE_IS_SYSTEM;
5339 String packageName = deletedPackage.packageName;
5340 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5341 if (packageName == null) {
5342 Log.w(TAG, "Attempt to delete null packageName.");
5343 return;
5344 }
5345 PackageParser.Package oldPkg;
5346 PackageSetting oldPkgSetting;
5347 synchronized (mPackages) {
5348 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005349 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5351 (oldPkgSetting == null)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005352 Log.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 return;
5354 }
5355 }
5356 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5357 res.removedInfo.removedPackage = packageName;
5358 // Remove existing system package
5359 removePackageLI(oldPkg, true);
5360 synchronized (mPackages) {
5361 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
5362 }
5363
5364 // Successfully disabled the old package. Now proceed with re-installation
5365 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5366 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005367 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005369 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5371 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5372 }
5373 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005374 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 updatedSettings = true;
5376 }
5377
5378 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5379 //update signature on the new package setting
5380 //this should always succeed, since we checked the
5381 //signature earlier.
5382 synchronized(mPackages) {
5383 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
5384 parseFlags, true);
5385 }
5386 } else {
5387 // Re installation failed. Restore old information
5388 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005389 if (newPackage != null) {
5390 removePackageLI(newPackage, true);
5391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005393 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07005395 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 // Restore the old system information in Settings
5397 synchronized(mPackages) {
5398 if(updatedSettings) {
5399 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005400 mSettings.setInstallerPackageName(packageName,
5401 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 }
5403 mSettings.writeLP();
5404 }
5405 }
5406 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005407
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005408 // Utility method used to move dex files during install.
5409 private int moveDexFiles(PackageParser.Package newPackage) {
5410 int retCode;
5411 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5412 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5413 if (retCode != 0) {
5414 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
5415 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5416 }
5417 }
5418 return PackageManager.INSTALL_SUCCEEDED;
5419 }
5420
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005421 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005422 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005423 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 synchronized (mPackages) {
5425 //write settings. the installStatus will be incomplete at this stage.
5426 //note that the new package setting would have already been
5427 //added to mPackages. It hasn't been persisted yet.
5428 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5429 mSettings.writeLP();
5430 }
5431
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005432 if ((res.returnCode = moveDexFiles(newPackage))
5433 != PackageManager.INSTALL_SUCCEEDED) {
5434 // Discontinue if moving dex files failed.
5435 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005437 if((res.returnCode = setPermissionsLI(newPackage))
5438 != PackageManager.INSTALL_SUCCEEDED) {
5439 if (mInstaller != null) {
5440 mInstaller.rmdex(newPackage.mScanPath);
5441 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005442 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005444 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 synchronized (mPackages) {
5447 grantPermissionsLP(newPackage, true);
5448 res.name = pkgName;
5449 res.uid = newPackage.applicationInfo.uid;
5450 res.pkg = newPackage;
5451 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005452 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5454 //to update install status
5455 mSettings.writeLP();
5456 }
5457 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005458
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005459 private void installPackageLI(InstallArgs args,
5460 boolean newInstall, PackageInstalledInfo res) {
5461 int pFlags = args.flags;
5462 String installerPackageName = args.installerPackageName;
5463 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005464 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005465 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005466 boolean replace = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005467 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
5468 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005469 // Result object to be returned
5470 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5471
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005472 // Retrieve PackageSettings and parse package
5473 int parseFlags = PackageParser.PARSE_CHATTY |
5474 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5475 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5476 parseFlags |= mDefParseFlags;
5477 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5478 pp.setSeparateProcesses(mSeparateProcesses);
5479 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5480 null, mMetrics, parseFlags);
5481 if (pkg == null) {
5482 res.returnCode = pp.getParseError();
5483 return;
5484 }
5485 String pkgName = res.name = pkg.packageName;
5486 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5487 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5488 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5489 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005490 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005491 }
5492 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5493 res.returnCode = pp.getParseError();
5494 return;
5495 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005496 // Get rid of all references to package scan path via parser.
5497 pp = null;
5498 String oldCodePath = null;
5499 boolean systemApp = false;
5500 synchronized (mPackages) {
5501 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005502 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5503 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08005504 if (pkg.mOriginalPackages != null
5505 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005506 && mPackages.containsKey(oldName)) {
5507 // This package is derived from an original package,
5508 // and this device has been updating from that original
5509 // name. We must continue using the original name, so
5510 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08005511 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005512 pkgName = pkg.packageName;
5513 replace = true;
5514 } else if (mPackages.containsKey(pkgName)) {
5515 // This package, under its official name, already exists
5516 // on the device; we should replace it.
5517 replace = true;
5518 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005519 }
5520 PackageSetting ps = mSettings.mPackages.get(pkgName);
5521 if (ps != null) {
5522 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5523 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5524 systemApp = (ps.pkg.applicationInfo.flags &
5525 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005526 }
5527 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005528 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005529
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005530 if (systemApp && onSd) {
5531 // Disable updates to system apps on sdcard
5532 Log.w(TAG, "Cannot install updates to system apps on sdcard");
5533 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5534 return;
5535 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08005536
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005537 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5538 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5539 return;
5540 }
5541 // Set application objects path explicitly after the rename
5542 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005543 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005544 replacePackageLI(pkg, parseFlags, scanMode,
5545 installerPackageName, res);
5546 } else {
5547 installNewPackageLI(pkg, parseFlags, scanMode,
5548 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005549 }
5550 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005551
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005552 private int setPermissionsLI(PackageParser.Package newPackage) {
5553 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005554 int retCode = 0;
5555 // TODO Gross hack but fix later. Ideally move this to be a post installation
5556 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005557 if ((newPackage.applicationInfo.flags
5558 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
5559 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 try {
5561 extractPublicFiles(newPackage, destResourceFile);
5562 } catch (IOException e) {
5563 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
5564 " forward-locked app.");
5565 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5566 } finally {
5567 //TODO clean up the extracted public files
5568 }
5569 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005570 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005571 newPackage.applicationInfo.uid);
5572 } else {
5573 final int filePermissions =
5574 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005575 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 newPackage.applicationInfo.uid);
5577 }
5578 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005579 // The permissions on the resource file was set when it was copied for
5580 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005581 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005583 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005584 Log.e(TAG, "Couldn't set new package file permissions for " +
5585 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005587 // TODO Define new internal error
5588 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 }
5590 return PackageManager.INSTALL_SUCCEEDED;
5591 }
5592
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005593 private boolean isForwardLocked(PackageParser.Package pkg) {
5594 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 }
5596
5597 private void extractPublicFiles(PackageParser.Package newPackage,
5598 File publicZipFile) throws IOException {
5599 final ZipOutputStream publicZipOutStream =
5600 new ZipOutputStream(new FileOutputStream(publicZipFile));
5601 final ZipFile privateZip = new ZipFile(newPackage.mPath);
5602
5603 // Copy manifest, resources.arsc and res directory to public zip
5604
5605 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
5606 while (privateZipEntries.hasMoreElements()) {
5607 final ZipEntry zipEntry = privateZipEntries.nextElement();
5608 final String zipEntryName = zipEntry.getName();
5609 if ("AndroidManifest.xml".equals(zipEntryName)
5610 || "resources.arsc".equals(zipEntryName)
5611 || zipEntryName.startsWith("res/")) {
5612 try {
5613 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
5614 } catch (IOException e) {
5615 try {
5616 publicZipOutStream.close();
5617 throw e;
5618 } finally {
5619 publicZipFile.delete();
5620 }
5621 }
5622 }
5623 }
5624
5625 publicZipOutStream.close();
5626 FileUtils.setPermissions(
5627 publicZipFile.getAbsolutePath(),
5628 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
5629 -1, -1);
5630 }
5631
5632 private static void copyZipEntry(ZipEntry zipEntry,
5633 ZipFile inZipFile,
5634 ZipOutputStream outZipStream) throws IOException {
5635 byte[] buffer = new byte[4096];
5636 int num;
5637
5638 ZipEntry newEntry;
5639 if (zipEntry.getMethod() == ZipEntry.STORED) {
5640 // Preserve the STORED method of the input entry.
5641 newEntry = new ZipEntry(zipEntry);
5642 } else {
5643 // Create a new entry so that the compressed len is recomputed.
5644 newEntry = new ZipEntry(zipEntry.getName());
5645 }
5646 outZipStream.putNextEntry(newEntry);
5647
5648 InputStream data = inZipFile.getInputStream(zipEntry);
5649 while ((num = data.read(buffer)) > 0) {
5650 outZipStream.write(buffer, 0, num);
5651 }
5652 outZipStream.flush();
5653 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 private void deleteTempPackageFiles() {
5656 FilenameFilter filter = new FilenameFilter() {
5657 public boolean accept(File dir, String name) {
5658 return name.startsWith("vmdl") && name.endsWith(".tmp");
5659 }
5660 };
5661 String tmpFilesList[] = mAppInstallDir.list(filter);
5662 if(tmpFilesList == null) {
5663 return;
5664 }
5665 for(int i = 0; i < tmpFilesList.length; i++) {
5666 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
5667 tmpFile.delete();
5668 }
5669 }
5670
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005671 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 File tmpPackageFile;
5673 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005674 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 } catch (IOException e) {
5676 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
5677 return null;
5678 }
5679 try {
5680 FileUtils.setPermissions(
5681 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
5682 -1, -1);
5683 } catch (IOException e) {
5684 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
5685 return null;
5686 }
5687 return tmpPackageFile;
5688 }
5689
5690 public void deletePackage(final String packageName,
5691 final IPackageDeleteObserver observer,
5692 final int flags) {
5693 mContext.enforceCallingOrSelfPermission(
5694 android.Manifest.permission.DELETE_PACKAGES, null);
5695 // Queue up an async operation since the package deletion may take a little while.
5696 mHandler.post(new Runnable() {
5697 public void run() {
5698 mHandler.removeCallbacks(this);
5699 final boolean succeded = deletePackageX(packageName, true, true, flags);
5700 if (observer != null) {
5701 try {
5702 observer.packageDeleted(succeded);
5703 } catch (RemoteException e) {
5704 Log.i(TAG, "Observer no longer exists.");
5705 } //end catch
5706 } //end if
5707 } //end run
5708 });
5709 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 /**
5712 * This method is an internal method that could be get invoked either
5713 * to delete an installed package or to clean up a failed installation.
5714 * After deleting an installed package, a broadcast is sent to notify any
5715 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005716 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 * installation wouldn't have sent the initial broadcast either
5718 * The key steps in deleting a package are
5719 * deleting the package information in internal structures like mPackages,
5720 * deleting the packages base directories through installd
5721 * updating mSettings to reflect current status
5722 * persisting settings for later use
5723 * sending a broadcast if necessary
5724 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 private boolean deletePackageX(String packageName, boolean sendBroadCast,
5726 boolean deleteCodeAndResources, int flags) {
5727 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07005728 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005729
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08005730 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
5731 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
5732 try {
5733 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
5734 Log.w(TAG, "Not removing package " + packageName + ": has active device admin");
5735 return false;
5736 }
5737 } catch (RemoteException e) {
5738 }
5739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005740 synchronized (mInstallLock) {
5741 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
5742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07005745 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
5746 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
5747
5748 // If the removed package was a system update, the old system packaged
5749 // was re-enabled; we need to broadcast this information
5750 if (systemUpdate) {
5751 Bundle extras = new Bundle(1);
5752 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
5753 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5754
5755 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
5756 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
5757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08005759 // Force a gc here.
5760 Runtime.getRuntime().gc();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005761 // Delete the resources here after sending the broadcast to let
5762 // other processes clean up before deleting resources.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005763 if (info.args != null) {
5764 synchronized (mInstallLock) {
5765 info.args.doPostDeleteLI(deleteCodeAndResources);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005766 }
5767 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 return res;
5769 }
5770
5771 static class PackageRemovedInfo {
5772 String removedPackage;
5773 int uid = -1;
5774 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07005775 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005776 // Clean up resources deleted packages.
5777 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07005778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 void sendBroadcast(boolean fullRemove, boolean replacing) {
5780 Bundle extras = new Bundle(1);
5781 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
5782 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
5783 if (replacing) {
5784 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5785 }
5786 if (removedPackage != null) {
5787 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
5788 }
5789 if (removedUid >= 0) {
5790 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5791 }
5792 }
5793 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 /*
5796 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5797 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005798 * 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 -08005799 * delete a partially installed application.
5800 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005801 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 int flags) {
5803 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005804 if (outInfo != null) {
5805 outInfo.removedPackage = packageName;
5806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 removePackageLI(p, true);
5808 // Retrieve object to delete permissions for shared user later on
5809 PackageSetting deletedPs;
5810 synchronized (mPackages) {
5811 deletedPs = mSettings.mPackages.get(packageName);
5812 }
5813 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005814 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005816 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 if (retCode < 0) {
5818 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5819 + packageName + ", retcode=" + retCode);
5820 // we don't consider this to be a failure of the core package deletion
5821 }
5822 } else {
5823 //for emulator
5824 PackageParser.Package pkg = mPackages.get(packageName);
5825 File dataDir = new File(pkg.applicationInfo.dataDir);
5826 dataDir.delete();
5827 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005828 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005830 if (outInfo != null) {
5831 outInfo.removedUid = mSettings.removePackageLP(packageName);
5832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 }
5834 }
5835 synchronized (mPackages) {
5836 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5837 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005838 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005839 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08005840 if (deletedPs != null) {
5841 // remove from preferred activities.
5842 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
5843 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
5844 if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
5845 removed.add(pa);
5846 }
5847 }
5848 for (PreferredActivity pa : removed) {
5849 mSettings.mPreferredActivities.removeFilter(pa);
5850 }
5851 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005852 // Save settings now
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005853 mSettings.writeLP();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 }
5855 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 /*
5858 * Tries to delete system package.
5859 */
5860 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005861 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 ApplicationInfo applicationInfo = p.applicationInfo;
5863 //applicable for non-partially installed applications only
5864 if (applicationInfo == null) {
5865 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5866 return false;
5867 }
5868 PackageSetting ps = null;
5869 // Confirm if the system package has been updated
5870 // An updated system app can be deleted. This will also have to restore
5871 // the system pkg from system partition
5872 synchronized (mPackages) {
5873 ps = mSettings.getDisabledSystemPkg(p.packageName);
5874 }
5875 if (ps == null) {
5876 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5877 return false;
5878 } else {
5879 Log.i(TAG, "Deleting system pkg from data partition");
5880 }
5881 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005882 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005883 boolean deleteCodeAndResources = false;
5884 if (ps.versionCode < p.mVersionCode) {
5885 // Delete code and resources for downgrades
5886 deleteCodeAndResources = true;
5887 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5888 flags &= ~PackageManager.DONT_DELETE_DATA;
5889 }
5890 } else {
5891 // Preserve data by setting flag
5892 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5893 flags |= PackageManager.DONT_DELETE_DATA;
5894 }
5895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5897 if (!ret) {
5898 return false;
5899 }
5900 synchronized (mPackages) {
5901 // Reinstate the old system package
5902 mSettings.enableSystemPackageLP(p.packageName);
5903 }
5904 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005905 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005906 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005907 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 if (newPkg == null) {
5910 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5911 return false;
5912 }
5913 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005914 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 mSettings.writeLP();
5916 }
5917 return true;
5918 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5921 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5922 ApplicationInfo applicationInfo = p.applicationInfo;
5923 if (applicationInfo == null) {
5924 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5925 return false;
5926 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005927 if (outInfo != null) {
5928 outInfo.uid = applicationInfo.uid;
5929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930
5931 // Delete package data from internal structures and also remove data if flag is set
5932 removePackageDataLI(p, outInfo, flags);
5933
5934 // Delete application code and resources
5935 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005936 // TODO can pick up from PackageSettings as well
5937 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005938 PackageManager.INSTALL_EXTERNAL : 0;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005939 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5940 PackageManager.INSTALL_FORWARD_LOCK : 0;
5941 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005942 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 }
5944 return true;
5945 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 /*
5948 * This method handles package deletion in general
5949 */
5950 private boolean deletePackageLI(String packageName,
5951 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5952 if (packageName == null) {
5953 Log.w(TAG, "Attempt to delete null packageName.");
5954 return false;
5955 }
5956 PackageParser.Package p;
5957 boolean dataOnly = false;
5958 synchronized (mPackages) {
5959 p = mPackages.get(packageName);
5960 if (p == null) {
5961 //this retrieves partially installed apps
5962 dataOnly = true;
5963 PackageSetting ps = mSettings.mPackages.get(packageName);
5964 if (ps == null) {
5965 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5966 return false;
5967 }
5968 p = ps.pkg;
5969 }
5970 }
5971 if (p == null) {
5972 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5973 return false;
5974 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 if (dataOnly) {
5977 // Delete application data first
5978 removePackageDataLI(p, outInfo, flags);
5979 return true;
5980 }
5981 // At this point the package should have ApplicationInfo associated with it
5982 if (p.applicationInfo == null) {
5983 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5984 return false;
5985 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005986 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5988 Log.i(TAG, "Removing system package:"+p.packageName);
5989 // When an updated system application is deleted we delete the existing resources as well and
5990 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005991 ret = deleteSystemPackageLI(p, flags, outInfo);
5992 } else {
5993 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005994 // Kill application pre-emptively especially for apps on sd.
5995 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005996 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005998 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005999 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006001 public void clearApplicationUserData(final String packageName,
6002 final IPackageDataObserver observer) {
6003 mContext.enforceCallingOrSelfPermission(
6004 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
6005 // Queue up an async operation since the package deletion may take a little while.
6006 mHandler.post(new Runnable() {
6007 public void run() {
6008 mHandler.removeCallbacks(this);
6009 final boolean succeeded;
6010 synchronized (mInstallLock) {
6011 succeeded = clearApplicationUserDataLI(packageName);
6012 }
6013 if (succeeded) {
6014 // invoke DeviceStorageMonitor's update method to clear any notifications
6015 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
6016 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
6017 if (dsm != null) {
6018 dsm.updateMemory();
6019 }
6020 }
6021 if(observer != null) {
6022 try {
6023 observer.onRemoveCompleted(packageName, succeeded);
6024 } catch (RemoteException e) {
6025 Log.i(TAG, "Observer no longer exists.");
6026 }
6027 } //end if observer
6028 } //end run
6029 });
6030 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 private boolean clearApplicationUserDataLI(String packageName) {
6033 if (packageName == null) {
6034 Log.w(TAG, "Attempt to delete null packageName.");
6035 return false;
6036 }
6037 PackageParser.Package p;
6038 boolean dataOnly = false;
6039 synchronized (mPackages) {
6040 p = mPackages.get(packageName);
6041 if(p == null) {
6042 dataOnly = true;
6043 PackageSetting ps = mSettings.mPackages.get(packageName);
6044 if((ps == null) || (ps.pkg == null)) {
6045 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6046 return false;
6047 }
6048 p = ps.pkg;
6049 }
6050 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006051 boolean useEncryptedFSDir = false;
6052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 if(!dataOnly) {
6054 //need to check this only for fully installed applications
6055 if (p == null) {
6056 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6057 return false;
6058 }
6059 final ApplicationInfo applicationInfo = p.applicationInfo;
6060 if (applicationInfo == null) {
6061 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
6062 return false;
6063 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006064 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 }
6066 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006067 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006068 if (retCode < 0) {
6069 Log.w(TAG, "Couldn't remove cache files for package: "
6070 + packageName);
6071 return false;
6072 }
6073 }
6074 return true;
6075 }
6076
6077 public void deleteApplicationCacheFiles(final String packageName,
6078 final IPackageDataObserver observer) {
6079 mContext.enforceCallingOrSelfPermission(
6080 android.Manifest.permission.DELETE_CACHE_FILES, null);
6081 // Queue up an async operation since the package deletion may take a little while.
6082 mHandler.post(new Runnable() {
6083 public void run() {
6084 mHandler.removeCallbacks(this);
6085 final boolean succeded;
6086 synchronized (mInstallLock) {
6087 succeded = deleteApplicationCacheFilesLI(packageName);
6088 }
6089 if(observer != null) {
6090 try {
6091 observer.onRemoveCompleted(packageName, succeded);
6092 } catch (RemoteException e) {
6093 Log.i(TAG, "Observer no longer exists.");
6094 }
6095 } //end if observer
6096 } //end run
6097 });
6098 }
6099
6100 private boolean deleteApplicationCacheFilesLI(String packageName) {
6101 if (packageName == null) {
6102 Log.w(TAG, "Attempt to delete null packageName.");
6103 return false;
6104 }
6105 PackageParser.Package p;
6106 synchronized (mPackages) {
6107 p = mPackages.get(packageName);
6108 }
6109 if (p == null) {
6110 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6111 return false;
6112 }
6113 final ApplicationInfo applicationInfo = p.applicationInfo;
6114 if (applicationInfo == null) {
6115 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
6116 return false;
6117 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006118 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006119 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006120 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 if (retCode < 0) {
6122 Log.w(TAG, "Couldn't remove cache files for package: "
6123 + packageName);
6124 return false;
6125 }
6126 }
6127 return true;
6128 }
6129
6130 public void getPackageSizeInfo(final String packageName,
6131 final IPackageStatsObserver observer) {
6132 mContext.enforceCallingOrSelfPermission(
6133 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6134 // Queue up an async operation since the package deletion may take a little while.
6135 mHandler.post(new Runnable() {
6136 public void run() {
6137 mHandler.removeCallbacks(this);
6138 PackageStats lStats = new PackageStats(packageName);
6139 final boolean succeded;
6140 synchronized (mInstallLock) {
6141 succeded = getPackageSizeInfoLI(packageName, lStats);
6142 }
6143 if(observer != null) {
6144 try {
6145 observer.onGetStatsCompleted(lStats, succeded);
6146 } catch (RemoteException e) {
6147 Log.i(TAG, "Observer no longer exists.");
6148 }
6149 } //end if observer
6150 } //end run
6151 });
6152 }
6153
6154 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6155 if (packageName == null) {
6156 Log.w(TAG, "Attempt to get size of null packageName.");
6157 return false;
6158 }
6159 PackageParser.Package p;
6160 boolean dataOnly = false;
6161 synchronized (mPackages) {
6162 p = mPackages.get(packageName);
6163 if(p == null) {
6164 dataOnly = true;
6165 PackageSetting ps = mSettings.mPackages.get(packageName);
6166 if((ps == null) || (ps.pkg == null)) {
6167 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
6168 return false;
6169 }
6170 p = ps.pkg;
6171 }
6172 }
6173 String publicSrcDir = null;
6174 if(!dataOnly) {
6175 final ApplicationInfo applicationInfo = p.applicationInfo;
6176 if (applicationInfo == null) {
6177 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
6178 return false;
6179 }
6180 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6181 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006182 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 if (mInstaller != null) {
6184 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08006185 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 if (res < 0) {
6187 return false;
6188 } else {
6189 return true;
6190 }
6191 }
6192 return true;
6193 }
6194
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 public void addPackageToPreferred(String packageName) {
6197 mContext.enforceCallingOrSelfPermission(
6198 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006199 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006200 }
6201
6202 public void removePackageFromPreferred(String packageName) {
6203 mContext.enforceCallingOrSelfPermission(
6204 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006205 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
6207
6208 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006209 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 }
6211
6212 public void addPreferredActivity(IntentFilter filter, int match,
6213 ComponentName[] set, ComponentName activity) {
6214 mContext.enforceCallingOrSelfPermission(
6215 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6216
6217 synchronized (mPackages) {
6218 Log.i(TAG, "Adding preferred activity " + activity + ":");
6219 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6220 mSettings.mPreferredActivities.addFilter(
6221 new PreferredActivity(filter, match, set, activity));
6222 mSettings.writeLP();
6223 }
6224 }
6225
Satish Sampath8dbe6122009-06-02 23:35:54 +01006226 public void replacePreferredActivity(IntentFilter filter, int match,
6227 ComponentName[] set, ComponentName activity) {
6228 mContext.enforceCallingOrSelfPermission(
6229 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6230 if (filter.countActions() != 1) {
6231 throw new IllegalArgumentException(
6232 "replacePreferredActivity expects filter to have only 1 action.");
6233 }
6234 if (filter.countCategories() != 1) {
6235 throw new IllegalArgumentException(
6236 "replacePreferredActivity expects filter to have only 1 category.");
6237 }
6238 if (filter.countDataAuthorities() != 0
6239 || filter.countDataPaths() != 0
6240 || filter.countDataSchemes() != 0
6241 || filter.countDataTypes() != 0) {
6242 throw new IllegalArgumentException(
6243 "replacePreferredActivity expects filter to have no data authorities, " +
6244 "paths, schemes or types.");
6245 }
6246 synchronized (mPackages) {
6247 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6248 String action = filter.getAction(0);
6249 String category = filter.getCategory(0);
6250 while (it.hasNext()) {
6251 PreferredActivity pa = it.next();
6252 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6253 it.remove();
6254 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
6255 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6256 }
6257 }
6258 addPreferredActivity(filter, match, set, activity);
6259 }
6260 }
6261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 public void clearPackagePreferredActivities(String packageName) {
6263 mContext.enforceCallingOrSelfPermission(
6264 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6265
6266 synchronized (mPackages) {
6267 if (clearPackagePreferredActivitiesLP(packageName)) {
6268 mSettings.writeLP();
6269 }
6270 }
6271 }
6272
6273 boolean clearPackagePreferredActivitiesLP(String packageName) {
6274 boolean changed = false;
6275 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6276 while (it.hasNext()) {
6277 PreferredActivity pa = it.next();
6278 if (pa.mActivity.getPackageName().equals(packageName)) {
6279 it.remove();
6280 changed = true;
6281 }
6282 }
6283 return changed;
6284 }
6285
6286 public int getPreferredActivities(List<IntentFilter> outFilters,
6287 List<ComponentName> outActivities, String packageName) {
6288
6289 int num = 0;
6290 synchronized (mPackages) {
6291 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6292 while (it.hasNext()) {
6293 PreferredActivity pa = it.next();
6294 if (packageName == null
6295 || pa.mActivity.getPackageName().equals(packageName)) {
6296 if (outFilters != null) {
6297 outFilters.add(new IntentFilter(pa));
6298 }
6299 if (outActivities != null) {
6300 outActivities.add(pa.mActivity);
6301 }
6302 }
6303 }
6304 }
6305
6306 return num;
6307 }
6308
6309 public void setApplicationEnabledSetting(String appPackageName,
6310 int newState, int flags) {
6311 setEnabledSetting(appPackageName, null, newState, flags);
6312 }
6313
6314 public void setComponentEnabledSetting(ComponentName componentName,
6315 int newState, int flags) {
6316 setEnabledSetting(componentName.getPackageName(),
6317 componentName.getClassName(), newState, flags);
6318 }
6319
6320 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006321 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
6323 || newState == COMPONENT_ENABLED_STATE_ENABLED
6324 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
6325 throw new IllegalArgumentException("Invalid new component state: "
6326 + newState);
6327 }
6328 PackageSetting pkgSetting;
6329 final int uid = Binder.getCallingUid();
6330 final int permission = mContext.checkCallingPermission(
6331 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
6332 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006333 boolean sendNow = false;
6334 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006335 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006337 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006338 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006339 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006341 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006343 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006344 }
6345 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006346 "Unknown component: " + packageName
6347 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 }
6349 if (!allowedByPermission && (uid != pkgSetting.userId)) {
6350 throw new SecurityException(
6351 "Permission Denial: attempt to change component state from pid="
6352 + Binder.getCallingPid()
6353 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
6354 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006355 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 // We're dealing with an application/package level state change
6357 pkgSetting.enabled = newState;
6358 } else {
6359 // We're dealing with a component level state change
6360 switch (newState) {
6361 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006362 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 break;
6364 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006365 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 break;
6367 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006368 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006369 break;
6370 default:
6371 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006372 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 }
6374 }
6375 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006376 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006377 components = mPendingBroadcasts.get(packageName);
6378 boolean newPackage = components == null;
6379 if (newPackage) {
6380 components = new ArrayList<String>();
6381 }
6382 if (!components.contains(componentName)) {
6383 components.add(componentName);
6384 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006385 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6386 sendNow = true;
6387 // Purge entry from pending broadcast list if another one exists already
6388 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006389 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006390 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006391 if (newPackage) {
6392 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006393 }
6394 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6395 // Schedule a message
6396 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6397 }
6398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 long callingId = Binder.clearCallingIdentity();
6402 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006403 if (sendNow) {
6404 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006405 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 } finally {
6408 Binder.restoreCallingIdentity(callingId);
6409 }
6410 }
6411
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006412 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006413 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6414 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6415 + " components=" + componentNames);
6416 Bundle extras = new Bundle(4);
6417 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6418 String nameList[] = new String[componentNames.size()];
6419 componentNames.toArray(nameList);
6420 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006421 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
6422 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006423 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006424 }
6425
Jacek Surazski65e13172009-04-28 15:26:38 +02006426 public String getInstallerPackageName(String packageName) {
6427 synchronized (mPackages) {
6428 PackageSetting pkg = mSettings.mPackages.get(packageName);
6429 if (pkg == null) {
6430 throw new IllegalArgumentException("Unknown package: " + packageName);
6431 }
6432 return pkg.installerPackageName;
6433 }
6434 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 public int getApplicationEnabledSetting(String appPackageName) {
6437 synchronized (mPackages) {
6438 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
6439 if (pkg == null) {
6440 throw new IllegalArgumentException("Unknown package: " + appPackageName);
6441 }
6442 return pkg.enabled;
6443 }
6444 }
6445
6446 public int getComponentEnabledSetting(ComponentName componentName) {
6447 synchronized (mPackages) {
6448 final String packageNameStr = componentName.getPackageName();
6449 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
6450 if (pkg == null) {
6451 throw new IllegalArgumentException("Unknown component: " + componentName);
6452 }
6453 final String classNameStr = componentName.getClassName();
6454 return pkg.currentEnabledStateLP(classNameStr);
6455 }
6456 }
6457
6458 public void enterSafeMode() {
6459 if (!mSystemReady) {
6460 mSafeMode = true;
6461 }
6462 }
6463
6464 public void systemReady() {
6465 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006466
6467 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006468 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006469 mContext.getContentResolver(),
6470 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006471 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006472 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006473 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006474 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 }
6476
6477 public boolean isSafeMode() {
6478 return mSafeMode;
6479 }
6480
6481 public boolean hasSystemUidErrors() {
6482 return mHasSystemUidErrors;
6483 }
6484
6485 static String arrayToString(int[] array) {
6486 StringBuffer buf = new StringBuffer(128);
6487 buf.append('[');
6488 if (array != null) {
6489 for (int i=0; i<array.length; i++) {
6490 if (i > 0) buf.append(", ");
6491 buf.append(array[i]);
6492 }
6493 }
6494 buf.append(']');
6495 return buf.toString();
6496 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 @Override
6499 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6500 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6501 != PackageManager.PERMISSION_GRANTED) {
6502 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6503 + Binder.getCallingPid()
6504 + ", uid=" + Binder.getCallingUid()
6505 + " without permission "
6506 + android.Manifest.permission.DUMP);
6507 return;
6508 }
6509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006510 synchronized (mPackages) {
6511 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006512 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006513 pw.println(" ");
6514 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006515 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 pw.println(" ");
6517 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006518 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 pw.println(" ");
6520 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006521 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006522 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 pw.println("Permissions:");
6524 {
6525 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006526 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
6527 pw.print(Integer.toHexString(System.identityHashCode(p)));
6528 pw.println("):");
6529 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
6530 pw.print(" uid="); pw.print(p.uid);
6531 pw.print(" gids="); pw.print(arrayToString(p.gids));
6532 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 }
6534 }
6535 pw.println(" ");
6536 pw.println("Packages:");
6537 {
6538 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006539 pw.print(" Package [");
6540 pw.print(ps.realName != null ? ps.realName : ps.name);
6541 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006542 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6543 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006544 if (ps.realName != null) {
6545 pw.print(" compat name="); pw.println(ps.name);
6546 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006547 pw.print(" userId="); pw.print(ps.userId);
6548 pw.print(" gids="); pw.println(arrayToString(ps.gids));
6549 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6550 pw.print(" pkg="); pw.println(ps.pkg);
6551 pw.print(" codePath="); pw.println(ps.codePathString);
6552 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006554 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006555 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006556 pw.print(" supportsScreens=[");
6557 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006558 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006559 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006560 if (!first) pw.print(", ");
6561 first = false;
6562 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006564 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006565 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006566 if (!first) pw.print(", ");
6567 first = false;
6568 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006569 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006570 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006571 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006572 if (!first) pw.print(", ");
6573 first = false;
6574 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006576 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006577 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006578 if (!first) pw.print(", ");
6579 first = false;
6580 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006581 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006582 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006583 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
6584 if (!first) pw.print(", ");
6585 first = false;
6586 pw.print("anyDensity");
6587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006588 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006589 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006590 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
6591 pw.print(" signatures="); pw.println(ps.signatures);
6592 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
6593 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
6594 pw.print(" installStatus="); pw.print(ps.installStatus);
6595 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006596 if (ps.disabledComponents.size() > 0) {
6597 pw.println(" disabledComponents:");
6598 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006599 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006600 }
6601 }
6602 if (ps.enabledComponents.size() > 0) {
6603 pw.println(" enabledComponents:");
6604 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006605 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006606 }
6607 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006608 if (ps.grantedPermissions.size() > 0) {
6609 pw.println(" grantedPermissions:");
6610 for (String s : ps.grantedPermissions) {
6611 pw.print(" "); pw.println(s);
6612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006614 if (ps.loadedPermissions.size() > 0) {
6615 pw.println(" loadedPermissions:");
6616 for (String s : ps.loadedPermissions) {
6617 pw.print(" "); pw.println(s);
6618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 }
6620 }
6621 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006622 if (mSettings.mRenamedPackages.size() > 0) {
6623 pw.println(" ");
6624 pw.println("Renamed packages:");
6625 for (HashMap.Entry<String, String> e
6626 : mSettings.mRenamedPackages.entrySet()) {
6627 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
6628 pw.println(e.getValue());
6629 }
6630 }
6631 if (mSettings.mDisabledSysPackages.size() > 0) {
6632 pw.println(" ");
6633 pw.println("Hidden system packages:");
6634 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
6635 pw.print(" Package [");
6636 pw.print(ps.realName != null ? ps.realName : ps.name);
6637 pw.print("] (");
6638 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6639 pw.println("):");
6640 if (ps.realName != null) {
6641 pw.print(" compat name="); pw.println(ps.name);
6642 }
6643 pw.print(" userId="); pw.println(ps.userId);
6644 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6645 pw.print(" codePath="); pw.println(ps.codePathString);
6646 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
6647 }
6648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 pw.println(" ");
6650 pw.println("Shared Users:");
6651 {
6652 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006653 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
6654 pw.print(Integer.toHexString(System.identityHashCode(su)));
6655 pw.println("):");
6656 pw.print(" userId="); pw.print(su.userId);
6657 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 pw.println(" grantedPermissions:");
6659 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006660 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006661 }
6662 pw.println(" loadedPermissions:");
6663 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006664 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 }
6666 }
6667 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006669 pw.println(" ");
6670 pw.println("Settings parse messages:");
6671 pw.println(mSettings.mReadMessages.toString());
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006672
6673 pw.println(" ");
6674 pw.println("Package warning messages:");
6675 File fname = getSettingsProblemFile();
6676 FileInputStream in;
6677 try {
6678 in = new FileInputStream(fname);
6679 int avail = in.available();
6680 byte[] data = new byte[avail];
6681 in.read(data);
6682 pw.println(new String(data));
6683 } catch (FileNotFoundException e) {
6684 } catch (IOException e) {
6685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006687
6688 synchronized (mProviders) {
6689 pw.println(" ");
6690 pw.println("Registered ContentProviders:");
6691 for (PackageParser.Provider p : mProviders.values()) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006692 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006693 pw.println(p.toString());
6694 }
6695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006696 }
6697
6698 static final class BasePermission {
6699 final static int TYPE_NORMAL = 0;
6700 final static int TYPE_BUILTIN = 1;
6701 final static int TYPE_DYNAMIC = 2;
6702
6703 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006704 String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 final int type;
6706 PackageParser.Permission perm;
6707 PermissionInfo pendingInfo;
6708 int uid;
6709 int[] gids;
6710
6711 BasePermission(String _name, String _sourcePackage, int _type) {
6712 name = _name;
6713 sourcePackage = _sourcePackage;
6714 type = _type;
6715 }
6716 }
6717
6718 static class PackageSignatures {
6719 private Signature[] mSignatures;
6720
6721 PackageSignatures(Signature[] sigs) {
6722 assignSignatures(sigs);
6723 }
6724
6725 PackageSignatures() {
6726 }
6727
6728 void writeXml(XmlSerializer serializer, String tagName,
6729 ArrayList<Signature> pastSignatures) throws IOException {
6730 if (mSignatures == null) {
6731 return;
6732 }
6733 serializer.startTag(null, tagName);
6734 serializer.attribute(null, "count",
6735 Integer.toString(mSignatures.length));
6736 for (int i=0; i<mSignatures.length; i++) {
6737 serializer.startTag(null, "cert");
6738 final Signature sig = mSignatures[i];
6739 final int sigHash = sig.hashCode();
6740 final int numPast = pastSignatures.size();
6741 int j;
6742 for (j=0; j<numPast; j++) {
6743 Signature pastSig = pastSignatures.get(j);
6744 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
6745 serializer.attribute(null, "index", Integer.toString(j));
6746 break;
6747 }
6748 }
6749 if (j >= numPast) {
6750 pastSignatures.add(sig);
6751 serializer.attribute(null, "index", Integer.toString(numPast));
6752 serializer.attribute(null, "key", sig.toCharsString());
6753 }
6754 serializer.endTag(null, "cert");
6755 }
6756 serializer.endTag(null, tagName);
6757 }
6758
6759 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
6760 throws IOException, XmlPullParserException {
6761 String countStr = parser.getAttributeValue(null, "count");
6762 if (countStr == null) {
6763 reportSettingsProblem(Log.WARN,
6764 "Error in package manager settings: <signatures> has"
6765 + " no count at " + parser.getPositionDescription());
6766 XmlUtils.skipCurrentTag(parser);
6767 }
6768 final int count = Integer.parseInt(countStr);
6769 mSignatures = new Signature[count];
6770 int pos = 0;
6771
6772 int outerDepth = parser.getDepth();
6773 int type;
6774 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6775 && (type != XmlPullParser.END_TAG
6776 || parser.getDepth() > outerDepth)) {
6777 if (type == XmlPullParser.END_TAG
6778 || type == XmlPullParser.TEXT) {
6779 continue;
6780 }
6781
6782 String tagName = parser.getName();
6783 if (tagName.equals("cert")) {
6784 if (pos < count) {
6785 String index = parser.getAttributeValue(null, "index");
6786 if (index != null) {
6787 try {
6788 int idx = Integer.parseInt(index);
6789 String key = parser.getAttributeValue(null, "key");
6790 if (key == null) {
6791 if (idx >= 0 && idx < pastSignatures.size()) {
6792 Signature sig = pastSignatures.get(idx);
6793 if (sig != null) {
6794 mSignatures[pos] = pastSignatures.get(idx);
6795 pos++;
6796 } else {
6797 reportSettingsProblem(Log.WARN,
6798 "Error in package manager settings: <cert> "
6799 + "index " + index + " is not defined at "
6800 + parser.getPositionDescription());
6801 }
6802 } else {
6803 reportSettingsProblem(Log.WARN,
6804 "Error in package manager settings: <cert> "
6805 + "index " + index + " is out of bounds at "
6806 + parser.getPositionDescription());
6807 }
6808 } else {
6809 while (pastSignatures.size() <= idx) {
6810 pastSignatures.add(null);
6811 }
6812 Signature sig = new Signature(key);
6813 pastSignatures.set(idx, sig);
6814 mSignatures[pos] = sig;
6815 pos++;
6816 }
6817 } catch (NumberFormatException e) {
6818 reportSettingsProblem(Log.WARN,
6819 "Error in package manager settings: <cert> "
6820 + "index " + index + " is not a number at "
6821 + parser.getPositionDescription());
6822 }
6823 } else {
6824 reportSettingsProblem(Log.WARN,
6825 "Error in package manager settings: <cert> has"
6826 + " no index at " + parser.getPositionDescription());
6827 }
6828 } else {
6829 reportSettingsProblem(Log.WARN,
6830 "Error in package manager settings: too "
6831 + "many <cert> tags, expected " + count
6832 + " at " + parser.getPositionDescription());
6833 }
6834 } else {
6835 reportSettingsProblem(Log.WARN,
6836 "Unknown element under <cert>: "
6837 + parser.getName());
6838 }
6839 XmlUtils.skipCurrentTag(parser);
6840 }
6841
6842 if (pos < count) {
6843 // Should never happen -- there is an error in the written
6844 // settings -- but if it does we don't want to generate
6845 // a bad array.
6846 Signature[] newSigs = new Signature[pos];
6847 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
6848 mSignatures = newSigs;
6849 }
6850 }
6851
6852 /**
6853 * If any of the given 'sigs' is contained in the existing signatures,
6854 * then completely replace the current signatures with the ones in
6855 * 'sigs'. This is used for updating an existing package to a newly
6856 * installed version.
6857 */
6858 boolean updateSignatures(Signature[] sigs, boolean update) {
6859 if (mSignatures == null) {
6860 if (update) {
6861 assignSignatures(sigs);
6862 }
6863 return true;
6864 }
6865 if (sigs == null) {
6866 return false;
6867 }
6868
6869 for (int i=0; i<sigs.length; i++) {
6870 Signature sig = sigs[i];
6871 for (int j=0; j<mSignatures.length; j++) {
6872 if (mSignatures[j].equals(sig)) {
6873 if (update) {
6874 assignSignatures(sigs);
6875 }
6876 return true;
6877 }
6878 }
6879 }
6880 return false;
6881 }
6882
6883 /**
6884 * If any of the given 'sigs' is contained in the existing signatures,
6885 * then add in any new signatures found in 'sigs'. This is used for
6886 * including a new package into an existing shared user id.
6887 */
6888 boolean mergeSignatures(Signature[] sigs, boolean update) {
6889 if (mSignatures == null) {
6890 if (update) {
6891 assignSignatures(sigs);
6892 }
6893 return true;
6894 }
6895 if (sigs == null) {
6896 return false;
6897 }
6898
6899 Signature[] added = null;
6900 int addedCount = 0;
6901 boolean haveMatch = false;
6902 for (int i=0; i<sigs.length; i++) {
6903 Signature sig = sigs[i];
6904 boolean found = false;
6905 for (int j=0; j<mSignatures.length; j++) {
6906 if (mSignatures[j].equals(sig)) {
6907 found = true;
6908 haveMatch = true;
6909 break;
6910 }
6911 }
6912
6913 if (!found) {
6914 if (added == null) {
6915 added = new Signature[sigs.length];
6916 }
6917 added[i] = sig;
6918 addedCount++;
6919 }
6920 }
6921
6922 if (!haveMatch) {
6923 // Nothing matched -- reject the new signatures.
6924 return false;
6925 }
6926 if (added == null) {
6927 // Completely matched -- nothing else to do.
6928 return true;
6929 }
6930
6931 // Add additional signatures in.
6932 if (update) {
6933 Signature[] total = new Signature[addedCount+mSignatures.length];
6934 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6935 int j = mSignatures.length;
6936 for (int i=0; i<added.length; i++) {
6937 if (added[i] != null) {
6938 total[j] = added[i];
6939 j++;
6940 }
6941 }
6942 mSignatures = total;
6943 }
6944 return true;
6945 }
6946
6947 private void assignSignatures(Signature[] sigs) {
6948 if (sigs == null) {
6949 mSignatures = null;
6950 return;
6951 }
6952 mSignatures = new Signature[sigs.length];
6953 for (int i=0; i<sigs.length; i++) {
6954 mSignatures[i] = sigs[i];
6955 }
6956 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 @Override
6959 public String toString() {
6960 StringBuffer buf = new StringBuffer(128);
6961 buf.append("PackageSignatures{");
6962 buf.append(Integer.toHexString(System.identityHashCode(this)));
6963 buf.append(" [");
6964 if (mSignatures != null) {
6965 for (int i=0; i<mSignatures.length; i++) {
6966 if (i > 0) buf.append(", ");
6967 buf.append(Integer.toHexString(
6968 System.identityHashCode(mSignatures[i])));
6969 }
6970 }
6971 buf.append("]}");
6972 return buf.toString();
6973 }
6974 }
6975
6976 static class PreferredActivity extends IntentFilter {
6977 final int mMatch;
6978 final String[] mSetPackages;
6979 final String[] mSetClasses;
6980 final String[] mSetComponents;
6981 final ComponentName mActivity;
6982 final String mShortActivity;
6983 String mParseError;
6984
6985 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6986 ComponentName activity) {
6987 super(filter);
6988 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6989 mActivity = activity;
6990 mShortActivity = activity.flattenToShortString();
6991 mParseError = null;
6992 if (set != null) {
6993 final int N = set.length;
6994 String[] myPackages = new String[N];
6995 String[] myClasses = new String[N];
6996 String[] myComponents = new String[N];
6997 for (int i=0; i<N; i++) {
6998 ComponentName cn = set[i];
6999 if (cn == null) {
7000 mSetPackages = null;
7001 mSetClasses = null;
7002 mSetComponents = null;
7003 return;
7004 }
7005 myPackages[i] = cn.getPackageName().intern();
7006 myClasses[i] = cn.getClassName().intern();
7007 myComponents[i] = cn.flattenToShortString().intern();
7008 }
7009 mSetPackages = myPackages;
7010 mSetClasses = myClasses;
7011 mSetComponents = myComponents;
7012 } else {
7013 mSetPackages = null;
7014 mSetClasses = null;
7015 mSetComponents = null;
7016 }
7017 }
7018
7019 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
7020 IOException {
7021 mShortActivity = parser.getAttributeValue(null, "name");
7022 mActivity = ComponentName.unflattenFromString(mShortActivity);
7023 if (mActivity == null) {
7024 mParseError = "Bad activity name " + mShortActivity;
7025 }
7026 String matchStr = parser.getAttributeValue(null, "match");
7027 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
7028 String setCountStr = parser.getAttributeValue(null, "set");
7029 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
7030
7031 String[] myPackages = setCount > 0 ? new String[setCount] : null;
7032 String[] myClasses = setCount > 0 ? new String[setCount] : null;
7033 String[] myComponents = setCount > 0 ? new String[setCount] : null;
7034
7035 int setPos = 0;
7036
7037 int outerDepth = parser.getDepth();
7038 int type;
7039 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7040 && (type != XmlPullParser.END_TAG
7041 || parser.getDepth() > outerDepth)) {
7042 if (type == XmlPullParser.END_TAG
7043 || type == XmlPullParser.TEXT) {
7044 continue;
7045 }
7046
7047 String tagName = parser.getName();
7048 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
7049 // + parser.getDepth() + " tag=" + tagName);
7050 if (tagName.equals("set")) {
7051 String name = parser.getAttributeValue(null, "name");
7052 if (name == null) {
7053 if (mParseError == null) {
7054 mParseError = "No name in set tag in preferred activity "
7055 + mShortActivity;
7056 }
7057 } else if (setPos >= setCount) {
7058 if (mParseError == null) {
7059 mParseError = "Too many set tags in preferred activity "
7060 + mShortActivity;
7061 }
7062 } else {
7063 ComponentName cn = ComponentName.unflattenFromString(name);
7064 if (cn == null) {
7065 if (mParseError == null) {
7066 mParseError = "Bad set name " + name + " in preferred activity "
7067 + mShortActivity;
7068 }
7069 } else {
7070 myPackages[setPos] = cn.getPackageName();
7071 myClasses[setPos] = cn.getClassName();
7072 myComponents[setPos] = name;
7073 setPos++;
7074 }
7075 }
7076 XmlUtils.skipCurrentTag(parser);
7077 } else if (tagName.equals("filter")) {
7078 //Log.i(TAG, "Starting to parse filter...");
7079 readFromXml(parser);
7080 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
7081 // + parser.getDepth() + " tag=" + parser.getName());
7082 } else {
7083 reportSettingsProblem(Log.WARN,
7084 "Unknown element under <preferred-activities>: "
7085 + parser.getName());
7086 XmlUtils.skipCurrentTag(parser);
7087 }
7088 }
7089
7090 if (setPos != setCount) {
7091 if (mParseError == null) {
7092 mParseError = "Not enough set tags (expected " + setCount
7093 + " but found " + setPos + ") in " + mShortActivity;
7094 }
7095 }
7096
7097 mSetPackages = myPackages;
7098 mSetClasses = myClasses;
7099 mSetComponents = myComponents;
7100 }
7101
7102 public void writeToXml(XmlSerializer serializer) throws IOException {
7103 final int NS = mSetClasses != null ? mSetClasses.length : 0;
7104 serializer.attribute(null, "name", mShortActivity);
7105 serializer.attribute(null, "match", Integer.toHexString(mMatch));
7106 serializer.attribute(null, "set", Integer.toString(NS));
7107 for (int s=0; s<NS; s++) {
7108 serializer.startTag(null, "set");
7109 serializer.attribute(null, "name", mSetComponents[s]);
7110 serializer.endTag(null, "set");
7111 }
7112 serializer.startTag(null, "filter");
7113 super.writeToXml(serializer);
7114 serializer.endTag(null, "filter");
7115 }
7116
7117 boolean sameSet(List<ResolveInfo> query, int priority) {
7118 if (mSetPackages == null) return false;
7119 final int NQ = query.size();
7120 final int NS = mSetPackages.length;
7121 int numMatch = 0;
7122 for (int i=0; i<NQ; i++) {
7123 ResolveInfo ri = query.get(i);
7124 if (ri.priority != priority) continue;
7125 ActivityInfo ai = ri.activityInfo;
7126 boolean good = false;
7127 for (int j=0; j<NS; j++) {
7128 if (mSetPackages[j].equals(ai.packageName)
7129 && mSetClasses[j].equals(ai.name)) {
7130 numMatch++;
7131 good = true;
7132 break;
7133 }
7134 }
7135 if (!good) return false;
7136 }
7137 return numMatch == NS;
7138 }
7139 }
7140
7141 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007142 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007143
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007144 HashSet<String> grantedPermissions = new HashSet<String>();
7145 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007149 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007150 setFlags(pkgFlags);
7151 }
7152
7153 void setFlags(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007154 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007155 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08007156 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) |
7157 (pkgFlags & ApplicationInfo.FLAG_NEVER_ENCRYPT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 }
7159 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007161 /**
7162 * Settings base class for pending and resolved classes.
7163 */
7164 static class PackageSettingBase extends GrantedPermissions {
7165 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007166 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007167 File codePath;
7168 String codePathString;
7169 File resourcePath;
7170 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 private long timeStamp;
7172 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007173 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007174
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007175 boolean uidError;
7176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 PackageSignatures signatures = new PackageSignatures();
7178
7179 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007181 /* Explicitly disabled components */
7182 HashSet<String> disabledComponents = new HashSet<String>(0);
7183 /* Explicitly enabled components */
7184 HashSet<String> enabledComponents = new HashSet<String>(0);
7185 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7186 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007187
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007188 PackageSettingBase origPackage;
7189
Jacek Surazski65e13172009-04-28 15:26:38 +02007190 /* package name of the app that installed this package */
7191 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007193 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007194 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 super(pkgFlags);
7196 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007197 this.realName = realName;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007198 init(codePath, resourcePath, pVersionCode);
7199 }
7200
7201 void init(File codePath, File resourcePath, int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007202 this.codePath = codePath;
7203 this.codePathString = codePath.toString();
7204 this.resourcePath = resourcePath;
7205 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007206 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007208
Jacek Surazski65e13172009-04-28 15:26:38 +02007209 public void setInstallerPackageName(String packageName) {
7210 installerPackageName = packageName;
7211 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007212
Jacek Surazski65e13172009-04-28 15:26:38 +02007213 String getInstallerPackageName() {
7214 return installerPackageName;
7215 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007217 public void setInstallStatus(int newStatus) {
7218 installStatus = newStatus;
7219 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 public int getInstallStatus() {
7222 return installStatus;
7223 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007225 public void setTimeStamp(long newStamp) {
7226 if (newStamp != timeStamp) {
7227 timeStamp = newStamp;
7228 timeStampString = Long.toString(newStamp);
7229 }
7230 }
7231
7232 public void setTimeStamp(long newStamp, String newStampStr) {
7233 timeStamp = newStamp;
7234 timeStampString = newStampStr;
7235 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007237 public long getTimeStamp() {
7238 return timeStamp;
7239 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 public String getTimeStampStr() {
7242 return timeStampString;
7243 }
7244
7245 public void copyFrom(PackageSettingBase base) {
7246 grantedPermissions = base.grantedPermissions;
7247 gids = base.gids;
7248 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 timeStamp = base.timeStamp;
7251 timeStampString = base.timeStampString;
7252 signatures = base.signatures;
7253 permissionsFixed = base.permissionsFixed;
7254 disabledComponents = base.disabledComponents;
7255 enabledComponents = base.enabledComponents;
7256 enabled = base.enabled;
7257 installStatus = base.installStatus;
7258 }
7259
7260 void enableComponentLP(String componentClassName) {
7261 disabledComponents.remove(componentClassName);
7262 enabledComponents.add(componentClassName);
7263 }
7264
7265 void disableComponentLP(String componentClassName) {
7266 enabledComponents.remove(componentClassName);
7267 disabledComponents.add(componentClassName);
7268 }
7269
7270 void restoreComponentLP(String componentClassName) {
7271 enabledComponents.remove(componentClassName);
7272 disabledComponents.remove(componentClassName);
7273 }
7274
7275 int currentEnabledStateLP(String componentName) {
7276 if (enabledComponents.contains(componentName)) {
7277 return COMPONENT_ENABLED_STATE_ENABLED;
7278 } else if (disabledComponents.contains(componentName)) {
7279 return COMPONENT_ENABLED_STATE_DISABLED;
7280 } else {
7281 return COMPONENT_ENABLED_STATE_DEFAULT;
7282 }
7283 }
7284 }
7285
7286 /**
7287 * Settings data for a particular package we know about.
7288 */
7289 static final class PackageSetting extends PackageSettingBase {
7290 int userId;
7291 PackageParser.Package pkg;
7292 SharedUserSetting sharedUser;
7293
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007294 PackageSetting(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007295 int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007296 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007297 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 @Override
7300 public String toString() {
7301 return "PackageSetting{"
7302 + Integer.toHexString(System.identityHashCode(this))
7303 + " " + name + "/" + userId + "}";
7304 }
7305 }
7306
7307 /**
7308 * Settings data for a particular shared user ID we know about.
7309 */
7310 static final class SharedUserSetting extends GrantedPermissions {
7311 final String name;
7312 int userId;
7313 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
7314 final PackageSignatures signatures = new PackageSignatures();
7315
7316 SharedUserSetting(String _name, int _pkgFlags) {
7317 super(_pkgFlags);
7318 name = _name;
7319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 @Override
7322 public String toString() {
7323 return "SharedUserSetting{"
7324 + Integer.toHexString(System.identityHashCode(this))
7325 + " " + name + "/" + userId + "}";
7326 }
7327 }
7328
7329 /**
7330 * Holds information about dynamic settings.
7331 */
7332 private static final class Settings {
7333 private final File mSettingsFilename;
7334 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007335 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 private final HashMap<String, PackageSetting> mPackages =
7337 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007338 // List of replaced system applications
7339 final HashMap<String, PackageSetting> mDisabledSysPackages =
7340 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 // The user's preferred activities associated with particular intent
7343 // filters.
7344 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
7345 new IntentResolver<PreferredActivity, PreferredActivity>() {
7346 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007347 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007348 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007349 out.print(prefix); out.print(
7350 Integer.toHexString(System.identityHashCode(filter)));
7351 out.print(' ');
7352 out.print(filter.mActivity.flattenToShortString());
7353 out.print(" match=0x");
7354 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007356 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007358 out.print(prefix); out.print(" ");
7359 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 }
7361 }
7362 }
7363 };
7364 private final HashMap<String, SharedUserSetting> mSharedUsers =
7365 new HashMap<String, SharedUserSetting>();
7366 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
7367 private final SparseArray<Object> mOtherUserIds =
7368 new SparseArray<Object>();
7369
7370 // For reading/writing settings file.
7371 private final ArrayList<Signature> mPastSignatures =
7372 new ArrayList<Signature>();
7373
7374 // Mapping from permission names to info about them.
7375 final HashMap<String, BasePermission> mPermissions =
7376 new HashMap<String, BasePermission>();
7377
7378 // Mapping from permission tree names to info about them.
7379 final HashMap<String, BasePermission> mPermissionTrees =
7380 new HashMap<String, BasePermission>();
7381
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007382 // Packages that have been uninstalled and still need their external
7383 // storage data deleted.
7384 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
7385
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007386 // Packages that have been renamed since they were first installed.
7387 // Keys are the new names of the packages, values are the original
7388 // names. The packages appear everwhere else under their original
7389 // names.
7390 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
7391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 private final StringBuilder mReadMessages = new StringBuilder();
7393
7394 private static final class PendingPackage extends PackageSettingBase {
7395 final int sharedId;
7396
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007397 PendingPackage(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007398 int sharedId, int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007399 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 this.sharedId = sharedId;
7401 }
7402 }
7403 private final ArrayList<PendingPackage> mPendingPackages
7404 = new ArrayList<PendingPackage>();
7405
7406 Settings() {
7407 File dataDir = Environment.getDataDirectory();
7408 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08007409 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
7410 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007412 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007413 FileUtils.setPermissions(systemDir.toString(),
7414 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7415 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7416 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08007417 FileUtils.setPermissions(systemSecureDir.toString(),
7418 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7419 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7420 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 mSettingsFilename = new File(systemDir, "packages.xml");
7422 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007423 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007424 }
7425
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007426 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007427 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 int pkgFlags, boolean create, boolean add) {
7429 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007430 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007431 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007432 return p;
7433 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007434
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007435 PackageSetting peekPackageLP(String name) {
7436 return mPackages.get(name);
7437 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007438 PackageSetting p = mPackages.get(name);
7439 if (p != null && p.codePath.getPath().equals(codePath)) {
7440 return p;
7441 }
7442 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007443 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007444 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 void setInstallStatus(String pkgName, int status) {
7447 PackageSetting p = mPackages.get(pkgName);
7448 if(p != null) {
7449 if(p.getInstallStatus() != status) {
7450 p.setInstallStatus(status);
7451 }
7452 }
7453 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007454
Jacek Surazski65e13172009-04-28 15:26:38 +02007455 void setInstallerPackageName(String pkgName,
7456 String installerPkgName) {
7457 PackageSetting p = mPackages.get(pkgName);
7458 if(p != null) {
7459 p.setInstallerPackageName(installerPkgName);
7460 }
7461 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007462
Jacek Surazski65e13172009-04-28 15:26:38 +02007463 String getInstallerPackageName(String pkgName) {
7464 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007465 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02007466 }
7467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 int getInstallStatus(String pkgName) {
7469 PackageSetting p = mPackages.get(pkgName);
7470 if(p != null) {
7471 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 return -1;
7474 }
7475
7476 SharedUserSetting getSharedUserLP(String name,
7477 int pkgFlags, boolean create) {
7478 SharedUserSetting s = mSharedUsers.get(name);
7479 if (s == null) {
7480 if (!create) {
7481 return null;
7482 }
7483 s = new SharedUserSetting(name, pkgFlags);
7484 if (MULTIPLE_APPLICATION_UIDS) {
7485 s.userId = newUserIdLP(s);
7486 } else {
7487 s.userId = FIRST_APPLICATION_UID;
7488 }
7489 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
7490 // < 0 means we couldn't assign a userid; fall out and return
7491 // s, which is currently null
7492 if (s.userId >= 0) {
7493 mSharedUsers.put(name, s);
7494 }
7495 }
7496
7497 return s;
7498 }
7499
7500 int disableSystemPackageLP(String name) {
7501 PackageSetting p = mPackages.get(name);
7502 if(p == null) {
7503 Log.w(TAG, "Package:"+name+" is not an installed package");
7504 return -1;
7505 }
7506 PackageSetting dp = mDisabledSysPackages.get(name);
7507 // always make sure the system package code and resource paths dont change
7508 if(dp == null) {
7509 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7510 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7511 }
7512 mDisabledSysPackages.put(name, p);
7513 }
7514 return removePackageLP(name);
7515 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 PackageSetting enableSystemPackageLP(String name) {
7518 PackageSetting p = mDisabledSysPackages.get(name);
7519 if(p == null) {
7520 Log.w(TAG, "Package:"+name+" is not disabled");
7521 return null;
7522 }
7523 // Reset flag in ApplicationInfo object
7524 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7525 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7526 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007527 PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007528 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007529 mDisabledSysPackages.remove(name);
7530 return ret;
7531 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007532
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007533 PackageSetting addPackageLP(String name, String realName, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007534 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 PackageSetting p = mPackages.get(name);
7536 if (p != null) {
7537 if (p.userId == uid) {
7538 return p;
7539 }
7540 reportSettingsProblem(Log.ERROR,
7541 "Adding duplicate package, keeping first: " + name);
7542 return null;
7543 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007544 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 p.userId = uid;
7546 if (addUserIdLP(uid, p, name)) {
7547 mPackages.put(name, p);
7548 return p;
7549 }
7550 return null;
7551 }
7552
7553 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
7554 SharedUserSetting s = mSharedUsers.get(name);
7555 if (s != null) {
7556 if (s.userId == uid) {
7557 return s;
7558 }
7559 reportSettingsProblem(Log.ERROR,
7560 "Adding duplicate shared user, keeping first: " + name);
7561 return null;
7562 }
7563 s = new SharedUserSetting(name, pkgFlags);
7564 s.userId = uid;
7565 if (addUserIdLP(uid, s, name)) {
7566 mSharedUsers.put(name, s);
7567 return s;
7568 }
7569 return null;
7570 }
7571
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007572 // Transfer ownership of permissions from one package to another.
7573 private void transferPermissions(String origPkg, String newPkg) {
7574 // Transfer ownership of permissions to the new package.
7575 for (int i=0; i<2; i++) {
7576 HashMap<String, BasePermission> permissions =
7577 i == 0 ? mPermissionTrees : mPermissions;
7578 for (BasePermission bp : permissions.values()) {
7579 if (origPkg.equals(bp.sourcePackage)) {
7580 if (DEBUG_UPGRADE) Log.v(TAG,
7581 "Moving permission " + bp.name
7582 + " from pkg " + bp.sourcePackage
7583 + " to " + newPkg);
7584 bp.sourcePackage = newPkg;
7585 bp.perm = null;
7586 if (bp.pendingInfo != null) {
7587 bp.sourcePackage = newPkg;
7588 }
7589 bp.uid = 0;
7590 bp.gids = null;
7591 }
7592 }
7593 }
7594 }
7595
7596 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007597 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007598 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 PackageSetting p = mPackages.get(name);
7600 if (p != null) {
7601 if (!p.codePath.equals(codePath)) {
7602 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007603 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007604 // This is an updated system app with versions in both system
7605 // and data partition. Just let the most recent version
7606 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007607 Log.w(TAG, "Trying to update system app code path from " +
7608 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007609 } else {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007610 // Just a change in the code path is not an issue, but
7611 // let's log a message about it.
7612 Log.i(TAG, "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007613 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007615 }
7616 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 reportSettingsProblem(Log.WARN,
7618 "Package " + name + " shared user changed from "
7619 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
7620 + " to "
7621 + (sharedUser != null ? sharedUser.name : "<nothing>")
7622 + "; replacing with new");
7623 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007624 } else {
7625 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7626 // If what we are scanning is a system package, then
7627 // make it so, regardless of whether it was previously
7628 // installed only in the data partition.
7629 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007631 }
7632 }
7633 if (p == null) {
7634 // Create a new PackageSettings entry. this can end up here because
7635 // of code path mismatch or user id mismatch of an updated system partition
7636 if (!create) {
7637 return null;
7638 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007639 if (origPackage != null) {
7640 // We are consuming the data from an existing package.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007641 p = new PackageSetting(origPackage.name, name, codePath,
7642 resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007643 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
7644 + " is adopting original package " + origPackage.name);
7645 p.copyFrom(origPackage);
7646 p.sharedUser = origPackage.sharedUser;
7647 p.userId = origPackage.userId;
7648 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007649 mRenamedPackages.put(name, origPackage.name);
7650 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007651 // Update new package state.
7652 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007654 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007655 p.setTimeStamp(codePath.lastModified());
7656 p.sharedUser = sharedUser;
7657 if (sharedUser != null) {
7658 p.userId = sharedUser.userId;
7659 } else if (MULTIPLE_APPLICATION_UIDS) {
7660 // Clone the setting here for disabled system packages
7661 PackageSetting dis = mDisabledSysPackages.get(name);
7662 if (dis != null) {
7663 // For disabled packages a new setting is created
7664 // from the existing user id. This still has to be
7665 // added to list of user id's
7666 // Copy signatures from previous setting
7667 if (dis.signatures.mSignatures != null) {
7668 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
7669 }
7670 p.userId = dis.userId;
7671 // Clone permissions
7672 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
7673 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
7674 // Clone component info
7675 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
7676 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
7677 // Add new setting to list of user ids
7678 addUserIdLP(p.userId, p, name);
7679 } else {
7680 // Assign new user id
7681 p.userId = newUserIdLP(p);
7682 }
7683 } else {
7684 p.userId = FIRST_APPLICATION_UID;
7685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 }
7687 if (p.userId < 0) {
7688 reportSettingsProblem(Log.WARN,
7689 "Package " + name + " could not be assigned a valid uid");
7690 return null;
7691 }
7692 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007693 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007695 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007696 }
7697 }
7698 return p;
7699 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007700
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007701 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007702 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007703 String codePath = pkg.applicationInfo.sourceDir;
7704 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007705 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007706 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007707 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007708 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007709 p.codePath = new File(codePath);
7710 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007711 }
7712 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007713 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007714 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007715 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007716 p.resourcePath = new File(resourcePath);
7717 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007718 }
7719 // Update version code if needed
7720 if (pkg.mVersionCode != p.versionCode) {
7721 p.versionCode = pkg.mVersionCode;
7722 }
7723 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
7724 }
7725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 // Utility method that adds a PackageSetting to mPackages and
7727 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007728 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 SharedUserSetting sharedUser) {
7730 mPackages.put(name, p);
7731 if (sharedUser != null) {
7732 if (p.sharedUser != null && p.sharedUser != sharedUser) {
7733 reportSettingsProblem(Log.ERROR,
7734 "Package " + p.name + " was user "
7735 + p.sharedUser + " but is now " + sharedUser
7736 + "; I am not changing its files so it will probably fail!");
7737 p.sharedUser.packages.remove(p);
7738 } else if (p.userId != sharedUser.userId) {
7739 reportSettingsProblem(Log.ERROR,
7740 "Package " + p.name + " was user id " + p.userId
7741 + " but is now user " + sharedUser
7742 + " with id " + sharedUser.userId
7743 + "; I am not changing its files so it will probably fail!");
7744 }
7745
7746 sharedUser.packages.add(p);
7747 p.sharedUser = sharedUser;
7748 p.userId = sharedUser.userId;
7749 }
7750 }
7751
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007752 /*
7753 * Update the shared user setting when a package using
7754 * specifying the shared user id is removed. The gids
7755 * associated with each permission of the deleted package
7756 * are removed from the shared user's gid list only if its
7757 * not in use by other permissions of packages in the
7758 * shared user setting.
7759 */
7760 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007761 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
7762 Log.i(TAG, "Trying to update info for null package. Just ignoring");
7763 return;
7764 }
7765 // No sharedUserId
7766 if (deletedPs.sharedUser == null) {
7767 return;
7768 }
7769 SharedUserSetting sus = deletedPs.sharedUser;
7770 // Update permissions
7771 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
7772 boolean used = false;
7773 if (!sus.grantedPermissions.contains (eachPerm)) {
7774 continue;
7775 }
7776 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007777 if (pkg.pkg != null &&
7778 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
7779 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007780 used = true;
7781 break;
7782 }
7783 }
7784 if (!used) {
7785 // can safely delete this permission from list
7786 sus.grantedPermissions.remove(eachPerm);
7787 sus.loadedPermissions.remove(eachPerm);
7788 }
7789 }
7790 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007791 int newGids[] = globalGids;
7792 for (String eachPerm : sus.grantedPermissions) {
7793 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007794 if (bp != null) {
7795 newGids = appendInts(newGids, bp.gids);
7796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 }
7798 sus.gids = newGids;
7799 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007801 private int removePackageLP(String name) {
7802 PackageSetting p = mPackages.get(name);
7803 if (p != null) {
7804 mPackages.remove(name);
7805 if (p.sharedUser != null) {
7806 p.sharedUser.packages.remove(p);
7807 if (p.sharedUser.packages.size() == 0) {
7808 mSharedUsers.remove(p.sharedUser.name);
7809 removeUserIdLP(p.sharedUser.userId);
7810 return p.sharedUser.userId;
7811 }
7812 } else {
7813 removeUserIdLP(p.userId);
7814 return p.userId;
7815 }
7816 }
7817 return -1;
7818 }
7819
7820 private boolean addUserIdLP(int uid, Object obj, Object name) {
7821 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
7822 return false;
7823 }
7824
7825 if (uid >= FIRST_APPLICATION_UID) {
7826 int N = mUserIds.size();
7827 final int index = uid - FIRST_APPLICATION_UID;
7828 while (index >= N) {
7829 mUserIds.add(null);
7830 N++;
7831 }
7832 if (mUserIds.get(index) != null) {
7833 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007834 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 + " name=" + name);
7836 return false;
7837 }
7838 mUserIds.set(index, obj);
7839 } else {
7840 if (mOtherUserIds.get(uid) != null) {
7841 reportSettingsProblem(Log.ERROR,
7842 "Adding duplicate shared id: " + uid
7843 + " name=" + name);
7844 return false;
7845 }
7846 mOtherUserIds.put(uid, obj);
7847 }
7848 return true;
7849 }
7850
7851 public Object getUserIdLP(int uid) {
7852 if (uid >= FIRST_APPLICATION_UID) {
7853 int N = mUserIds.size();
7854 final int index = uid - FIRST_APPLICATION_UID;
7855 return index < N ? mUserIds.get(index) : null;
7856 } else {
7857 return mOtherUserIds.get(uid);
7858 }
7859 }
7860
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007861 private Set<String> findPackagesWithFlag(int flag) {
7862 Set<String> ret = new HashSet<String>();
7863 for (PackageSetting ps : mPackages.values()) {
7864 // Has to match atleast all the flag bits set on flag
7865 if ((ps.pkgFlags & flag) == flag) {
7866 ret.add(ps.name);
7867 }
7868 }
7869 return ret;
7870 }
7871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007872 private void removeUserIdLP(int uid) {
7873 if (uid >= FIRST_APPLICATION_UID) {
7874 int N = mUserIds.size();
7875 final int index = uid - FIRST_APPLICATION_UID;
7876 if (index < N) mUserIds.set(index, null);
7877 } else {
7878 mOtherUserIds.remove(uid);
7879 }
7880 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 void writeLP() {
7883 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
7884
7885 // Keep the old settings around until we know the new ones have
7886 // been successfully written.
7887 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007888 // Presence of backup settings file indicates that we failed
7889 // to persist settings earlier. So preserve the older
7890 // backup for future reference since the current settings
7891 // might have been corrupted.
7892 if (!mBackupSettingsFilename.exists()) {
7893 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
7894 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
7895 return;
7896 }
7897 } else {
7898 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07007899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007900 }
7901
7902 mPastSignatures.clear();
7903
7904 try {
7905 FileOutputStream str = new FileOutputStream(mSettingsFilename);
7906
7907 //XmlSerializer serializer = XmlUtils.serializerInstance();
7908 XmlSerializer serializer = new FastXmlSerializer();
7909 serializer.setOutput(str, "utf-8");
7910 serializer.startDocument(null, true);
7911 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
7912
7913 serializer.startTag(null, "packages");
7914
7915 serializer.startTag(null, "permission-trees");
7916 for (BasePermission bp : mPermissionTrees.values()) {
7917 writePermission(serializer, bp);
7918 }
7919 serializer.endTag(null, "permission-trees");
7920
7921 serializer.startTag(null, "permissions");
7922 for (BasePermission bp : mPermissions.values()) {
7923 writePermission(serializer, bp);
7924 }
7925 serializer.endTag(null, "permissions");
7926
7927 for (PackageSetting pkg : mPackages.values()) {
7928 writePackage(serializer, pkg);
7929 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7932 writeDisabledSysPackage(serializer, pkg);
7933 }
7934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 serializer.startTag(null, "preferred-activities");
7936 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7937 serializer.startTag(null, "item");
7938 pa.writeToXml(serializer);
7939 serializer.endTag(null, "item");
7940 }
7941 serializer.endTag(null, "preferred-activities");
7942
7943 for (SharedUserSetting usr : mSharedUsers.values()) {
7944 serializer.startTag(null, "shared-user");
7945 serializer.attribute(null, "name", usr.name);
7946 serializer.attribute(null, "userId",
7947 Integer.toString(usr.userId));
7948 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7949 serializer.startTag(null, "perms");
7950 for (String name : usr.grantedPermissions) {
7951 serializer.startTag(null, "item");
7952 serializer.attribute(null, "name", name);
7953 serializer.endTag(null, "item");
7954 }
7955 serializer.endTag(null, "perms");
7956 serializer.endTag(null, "shared-user");
7957 }
7958
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007959 if (mPackagesToBeCleaned.size() > 0) {
7960 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
7961 serializer.startTag(null, "cleaning-package");
7962 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
7963 serializer.endTag(null, "cleaning-package");
7964 }
7965 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007966
7967 if (mRenamedPackages.size() > 0) {
7968 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
7969 serializer.startTag(null, "renamed-package");
7970 serializer.attribute(null, "new", e.getKey());
7971 serializer.attribute(null, "old", e.getValue());
7972 serializer.endTag(null, "renamed-package");
7973 }
7974 }
7975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 serializer.endTag(null, "packages");
7977
7978 serializer.endDocument();
7979
7980 str.flush();
7981 str.close();
7982
7983 // New settings successfully written, old ones are no longer
7984 // needed.
7985 mBackupSettingsFilename.delete();
7986 FileUtils.setPermissions(mSettingsFilename.toString(),
7987 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7988 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7989 |FileUtils.S_IROTH,
7990 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007991
7992 // Write package list file now, use a JournaledFile.
7993 //
7994 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
7995 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
7996
7997 str = new FileOutputStream(journal.chooseForWrite());
7998 try {
7999 StringBuilder sb = new StringBuilder();
8000 for (PackageSetting pkg : mPackages.values()) {
8001 ApplicationInfo ai = pkg.pkg.applicationInfo;
8002 String dataPath = ai.dataDir;
8003 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
8004
8005 // Avoid any application that has a space in its path
8006 // or that is handled by the system.
8007 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
8008 continue;
8009
8010 // we store on each line the following information for now:
8011 //
8012 // pkgName - package name
8013 // userId - application-specific user id
8014 // debugFlag - 0 or 1 if the package is debuggable.
8015 // dataPath - path to package's data path
8016 //
8017 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
8018 //
8019 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
8020 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
8021 // system/core/run-as/run-as.c
8022 //
8023 sb.setLength(0);
8024 sb.append(ai.packageName);
8025 sb.append(" ");
8026 sb.append((int)ai.uid);
8027 sb.append(isDebug ? " 1 " : " 0 ");
8028 sb.append(dataPath);
8029 sb.append("\n");
8030 str.write(sb.toString().getBytes());
8031 }
8032 str.flush();
8033 str.close();
8034 journal.commit();
8035 }
8036 catch (Exception e) {
8037 journal.rollback();
8038 }
8039
8040 FileUtils.setPermissions(mPackageListFilename.toString(),
8041 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8042 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8043 |FileUtils.S_IROTH,
8044 -1, -1);
8045
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008046 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047
8048 } catch(XmlPullParserException e) {
8049 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 -08008050 } catch(java.io.IOException e) {
8051 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 -08008052 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008053 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008054 if (mSettingsFilename.exists()) {
8055 if (!mSettingsFilename.delete()) {
8056 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
8057 }
8058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008059 //Debug.stopMethodTracing();
8060 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008061
8062 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008063 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 serializer.startTag(null, "updated-package");
8065 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008066 if (pkg.realName != null) {
8067 serializer.attribute(null, "realName", pkg.realName);
8068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 serializer.attribute(null, "codePath", pkg.codePathString);
8070 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008071 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8073 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8074 }
8075 if (pkg.sharedUser == null) {
8076 serializer.attribute(null, "userId",
8077 Integer.toString(pkg.userId));
8078 } else {
8079 serializer.attribute(null, "sharedUserId",
8080 Integer.toString(pkg.userId));
8081 }
8082 serializer.startTag(null, "perms");
8083 if (pkg.sharedUser == null) {
8084 // If this is a shared user, the permissions will
8085 // be written there. We still need to write an
8086 // empty permissions list so permissionsFixed will
8087 // be set.
8088 for (final String name : pkg.grantedPermissions) {
8089 BasePermission bp = mPermissions.get(name);
8090 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
8091 // We only need to write signature or system permissions but this wont
8092 // match the semantics of grantedPermissions. So write all permissions.
8093 serializer.startTag(null, "item");
8094 serializer.attribute(null, "name", name);
8095 serializer.endTag(null, "item");
8096 }
8097 }
8098 }
8099 serializer.endTag(null, "perms");
8100 serializer.endTag(null, "updated-package");
8101 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008102
8103 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008104 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 serializer.startTag(null, "package");
8106 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008107 if (pkg.realName != null) {
8108 serializer.attribute(null, "realName", pkg.realName);
8109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 serializer.attribute(null, "codePath", pkg.codePathString);
8111 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8112 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8113 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008114 serializer.attribute(null, "flags",
8115 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008116 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008117 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 if (pkg.sharedUser == null) {
8119 serializer.attribute(null, "userId",
8120 Integer.toString(pkg.userId));
8121 } else {
8122 serializer.attribute(null, "sharedUserId",
8123 Integer.toString(pkg.userId));
8124 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008125 if (pkg.uidError) {
8126 serializer.attribute(null, "uidError", "true");
8127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
8129 serializer.attribute(null, "enabled",
8130 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
8131 ? "true" : "false");
8132 }
8133 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
8134 serializer.attribute(null, "installStatus", "false");
8135 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008136 if (pkg.installerPackageName != null) {
8137 serializer.attribute(null, "installer", pkg.installerPackageName);
8138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
8140 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8141 serializer.startTag(null, "perms");
8142 if (pkg.sharedUser == null) {
8143 // If this is a shared user, the permissions will
8144 // be written there. We still need to write an
8145 // empty permissions list so permissionsFixed will
8146 // be set.
8147 for (final String name : pkg.grantedPermissions) {
8148 serializer.startTag(null, "item");
8149 serializer.attribute(null, "name", name);
8150 serializer.endTag(null, "item");
8151 }
8152 }
8153 serializer.endTag(null, "perms");
8154 }
8155 if (pkg.disabledComponents.size() > 0) {
8156 serializer.startTag(null, "disabled-components");
8157 for (final String name : pkg.disabledComponents) {
8158 serializer.startTag(null, "item");
8159 serializer.attribute(null, "name", name);
8160 serializer.endTag(null, "item");
8161 }
8162 serializer.endTag(null, "disabled-components");
8163 }
8164 if (pkg.enabledComponents.size() > 0) {
8165 serializer.startTag(null, "enabled-components");
8166 for (final String name : pkg.enabledComponents) {
8167 serializer.startTag(null, "item");
8168 serializer.attribute(null, "name", name);
8169 serializer.endTag(null, "item");
8170 }
8171 serializer.endTag(null, "enabled-components");
8172 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 serializer.endTag(null, "package");
8175 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008177 void writePermission(XmlSerializer serializer, BasePermission bp)
8178 throws XmlPullParserException, java.io.IOException {
8179 if (bp.type != BasePermission.TYPE_BUILTIN
8180 && bp.sourcePackage != null) {
8181 serializer.startTag(null, "item");
8182 serializer.attribute(null, "name", bp.name);
8183 serializer.attribute(null, "package", bp.sourcePackage);
8184 if (DEBUG_SETTINGS) Log.v(TAG,
8185 "Writing perm: name=" + bp.name + " type=" + bp.type);
8186 if (bp.type == BasePermission.TYPE_DYNAMIC) {
8187 PermissionInfo pi = bp.perm != null ? bp.perm.info
8188 : bp.pendingInfo;
8189 if (pi != null) {
8190 serializer.attribute(null, "type", "dynamic");
8191 if (pi.icon != 0) {
8192 serializer.attribute(null, "icon",
8193 Integer.toString(pi.icon));
8194 }
8195 if (pi.nonLocalizedLabel != null) {
8196 serializer.attribute(null, "label",
8197 pi.nonLocalizedLabel.toString());
8198 }
8199 if (pi.protectionLevel !=
8200 PermissionInfo.PROTECTION_NORMAL) {
8201 serializer.attribute(null, "protection",
8202 Integer.toString(pi.protectionLevel));
8203 }
8204 }
8205 }
8206 serializer.endTag(null, "item");
8207 }
8208 }
8209
8210 String getReadMessagesLP() {
8211 return mReadMessages.toString();
8212 }
8213
Oscar Montemayora8529f62009-11-18 10:14:20 -08008214 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
8216 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008217 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 while(its.hasNext()) {
8219 String key = its.next();
8220 PackageSetting ps = mPackages.get(key);
8221 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08008222 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 }
8224 }
8225 return ret;
8226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 boolean readLP() {
8229 FileInputStream str = null;
8230 if (mBackupSettingsFilename.exists()) {
8231 try {
8232 str = new FileInputStream(mBackupSettingsFilename);
8233 mReadMessages.append("Reading from backup settings file\n");
8234 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008235 if (mSettingsFilename.exists()) {
8236 // If both the backup and settings file exist, we
8237 // ignore the settings since it might have been
8238 // corrupted.
8239 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
8240 mSettingsFilename.delete();
8241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 } catch (java.io.IOException e) {
8243 // We'll try for the normal settings file.
8244 }
8245 }
8246
8247 mPastSignatures.clear();
8248
8249 try {
8250 if (str == null) {
8251 if (!mSettingsFilename.exists()) {
8252 mReadMessages.append("No settings file found\n");
8253 Log.i(TAG, "No current settings file!");
8254 return false;
8255 }
8256 str = new FileInputStream(mSettingsFilename);
8257 }
8258 XmlPullParser parser = Xml.newPullParser();
8259 parser.setInput(str, null);
8260
8261 int type;
8262 while ((type=parser.next()) != XmlPullParser.START_TAG
8263 && type != XmlPullParser.END_DOCUMENT) {
8264 ;
8265 }
8266
8267 if (type != XmlPullParser.START_TAG) {
8268 mReadMessages.append("No start tag found in settings file\n");
8269 Log.e(TAG, "No start tag found in package manager settings");
8270 return false;
8271 }
8272
8273 int outerDepth = parser.getDepth();
8274 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8275 && (type != XmlPullParser.END_TAG
8276 || parser.getDepth() > outerDepth)) {
8277 if (type == XmlPullParser.END_TAG
8278 || type == XmlPullParser.TEXT) {
8279 continue;
8280 }
8281
8282 String tagName = parser.getName();
8283 if (tagName.equals("package")) {
8284 readPackageLP(parser);
8285 } else if (tagName.equals("permissions")) {
8286 readPermissionsLP(mPermissions, parser);
8287 } else if (tagName.equals("permission-trees")) {
8288 readPermissionsLP(mPermissionTrees, parser);
8289 } else if (tagName.equals("shared-user")) {
8290 readSharedUserLP(parser);
8291 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08008292 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 } else if (tagName.equals("preferred-activities")) {
8294 readPreferredActivitiesLP(parser);
8295 } else if(tagName.equals("updated-package")) {
8296 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008297 } else if (tagName.equals("cleaning-package")) {
8298 String name = parser.getAttributeValue(null, "name");
8299 if (name != null) {
8300 mPackagesToBeCleaned.add(name);
8301 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008302 } else if (tagName.equals("renamed-package")) {
8303 String nname = parser.getAttributeValue(null, "new");
8304 String oname = parser.getAttributeValue(null, "old");
8305 if (nname != null && oname != null) {
8306 mRenamedPackages.put(nname, oname);
8307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 } else {
8309 Log.w(TAG, "Unknown element under <packages>: "
8310 + parser.getName());
8311 XmlUtils.skipCurrentTag(parser);
8312 }
8313 }
8314
8315 str.close();
8316
8317 } catch(XmlPullParserException e) {
8318 mReadMessages.append("Error reading: " + e.toString());
8319 Log.e(TAG, "Error reading package manager settings", e);
8320
8321 } catch(java.io.IOException e) {
8322 mReadMessages.append("Error reading: " + e.toString());
8323 Log.e(TAG, "Error reading package manager settings", e);
8324
8325 }
8326
8327 int N = mPendingPackages.size();
8328 for (int i=0; i<N; i++) {
8329 final PendingPackage pp = mPendingPackages.get(i);
8330 Object idObj = getUserIdLP(pp.sharedId);
8331 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008332 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008333 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008334 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 if (p == null) {
8336 Log.w(TAG, "Unable to create application package for "
8337 + pp.name);
8338 continue;
8339 }
8340 p.copyFrom(pp);
8341 } else if (idObj != null) {
8342 String msg = "Bad package setting: package " + pp.name
8343 + " has shared uid " + pp.sharedId
8344 + " that is not a shared uid\n";
8345 mReadMessages.append(msg);
8346 Log.e(TAG, msg);
8347 } else {
8348 String msg = "Bad package setting: package " + pp.name
8349 + " has shared uid " + pp.sharedId
8350 + " that is not defined\n";
8351 mReadMessages.append(msg);
8352 Log.e(TAG, msg);
8353 }
8354 }
8355 mPendingPackages.clear();
8356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 mReadMessages.append("Read completed successfully: "
8358 + mPackages.size() + " packages, "
8359 + mSharedUsers.size() + " shared uids\n");
8360
8361 return true;
8362 }
8363
8364 private int readInt(XmlPullParser parser, String ns, String name,
8365 int defValue) {
8366 String v = parser.getAttributeValue(ns, name);
8367 try {
8368 if (v == null) {
8369 return defValue;
8370 }
8371 return Integer.parseInt(v);
8372 } catch (NumberFormatException e) {
8373 reportSettingsProblem(Log.WARN,
8374 "Error in package manager settings: attribute " +
8375 name + " has bad integer value " + v + " at "
8376 + parser.getPositionDescription());
8377 }
8378 return defValue;
8379 }
8380
8381 private void readPermissionsLP(HashMap<String, BasePermission> out,
8382 XmlPullParser parser)
8383 throws IOException, XmlPullParserException {
8384 int outerDepth = parser.getDepth();
8385 int type;
8386 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8387 && (type != XmlPullParser.END_TAG
8388 || parser.getDepth() > outerDepth)) {
8389 if (type == XmlPullParser.END_TAG
8390 || type == XmlPullParser.TEXT) {
8391 continue;
8392 }
8393
8394 String tagName = parser.getName();
8395 if (tagName.equals("item")) {
8396 String name = parser.getAttributeValue(null, "name");
8397 String sourcePackage = parser.getAttributeValue(null, "package");
8398 String ptype = parser.getAttributeValue(null, "type");
8399 if (name != null && sourcePackage != null) {
8400 boolean dynamic = "dynamic".equals(ptype);
8401 BasePermission bp = new BasePermission(name, sourcePackage,
8402 dynamic
8403 ? BasePermission.TYPE_DYNAMIC
8404 : BasePermission.TYPE_NORMAL);
8405 if (dynamic) {
8406 PermissionInfo pi = new PermissionInfo();
8407 pi.packageName = sourcePackage.intern();
8408 pi.name = name.intern();
8409 pi.icon = readInt(parser, null, "icon", 0);
8410 pi.nonLocalizedLabel = parser.getAttributeValue(
8411 null, "label");
8412 pi.protectionLevel = readInt(parser, null, "protection",
8413 PermissionInfo.PROTECTION_NORMAL);
8414 bp.pendingInfo = pi;
8415 }
8416 out.put(bp.name, bp);
8417 } else {
8418 reportSettingsProblem(Log.WARN,
8419 "Error in package manager settings: permissions has"
8420 + " no name at " + parser.getPositionDescription());
8421 }
8422 } else {
8423 reportSettingsProblem(Log.WARN,
8424 "Unknown element reading permissions: "
8425 + parser.getName() + " at "
8426 + parser.getPositionDescription());
8427 }
8428 XmlUtils.skipCurrentTag(parser);
8429 }
8430 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008432 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008433 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008434 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008435 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 String codePathStr = parser.getAttributeValue(null, "codePath");
8437 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008438 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008439 resourcePathStr = codePathStr;
8440 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008441 String version = parser.getAttributeValue(null, "version");
8442 int versionCode = 0;
8443 if (version != null) {
8444 try {
8445 versionCode = Integer.parseInt(version);
8446 } catch (NumberFormatException e) {
8447 }
8448 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008450 int pkgFlags = 0;
8451 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008452 PackageSetting ps = new PackageSetting(name, realName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008453 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008454 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 String timeStampStr = parser.getAttributeValue(null, "ts");
8456 if (timeStampStr != null) {
8457 try {
8458 long timeStamp = Long.parseLong(timeStampStr);
8459 ps.setTimeStamp(timeStamp, timeStampStr);
8460 } catch (NumberFormatException e) {
8461 }
8462 }
8463 String idStr = parser.getAttributeValue(null, "userId");
8464 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
8465 if(ps.userId <= 0) {
8466 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8467 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
8468 }
8469 int outerDepth = parser.getDepth();
8470 int type;
8471 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8472 && (type != XmlPullParser.END_TAG
8473 || parser.getDepth() > outerDepth)) {
8474 if (type == XmlPullParser.END_TAG
8475 || type == XmlPullParser.TEXT) {
8476 continue;
8477 }
8478
8479 String tagName = parser.getName();
8480 if (tagName.equals("perms")) {
8481 readGrantedPermissionsLP(parser,
8482 ps.grantedPermissions);
8483 } else {
8484 reportSettingsProblem(Log.WARN,
8485 "Unknown element under <updated-package>: "
8486 + parser.getName());
8487 XmlUtils.skipCurrentTag(parser);
8488 }
8489 }
8490 mDisabledSysPackages.put(name, ps);
8491 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 private void readPackageLP(XmlPullParser parser)
8494 throws XmlPullParserException, IOException {
8495 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008496 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497 String idStr = null;
8498 String sharedIdStr = null;
8499 String codePathStr = null;
8500 String resourcePathStr = null;
8501 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02008502 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008503 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 int pkgFlags = 0;
8505 String timeStampStr;
8506 long timeStamp = 0;
8507 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008508 String version = null;
8509 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008510 try {
8511 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008512 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008513 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008514 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8516 codePathStr = parser.getAttributeValue(null, "codePath");
8517 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008518 version = parser.getAttributeValue(null, "version");
8519 if (version != null) {
8520 try {
8521 versionCode = Integer.parseInt(version);
8522 } catch (NumberFormatException e) {
8523 }
8524 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008525 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008526
8527 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008529 try {
8530 pkgFlags = Integer.parseInt(systemStr);
8531 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 }
8533 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008534 // For backward compatibility
8535 systemStr = parser.getAttributeValue(null, "system");
8536 if (systemStr != null) {
8537 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
8538 } else {
8539 // Old settings that don't specify system... just treat
8540 // them as system, good enough.
8541 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008543 }
8544 timeStampStr = parser.getAttributeValue(null, "ts");
8545 if (timeStampStr != null) {
8546 try {
8547 timeStamp = Long.parseLong(timeStampStr);
8548 } catch (NumberFormatException e) {
8549 }
8550 }
8551 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
8552 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
8553 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8554 if (resourcePathStr == null) {
8555 resourcePathStr = codePathStr;
8556 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008557 if (realName != null) {
8558 realName = realName.intern();
8559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 if (name == null) {
8561 reportSettingsProblem(Log.WARN,
8562 "Error in package manager settings: <package> has no name at "
8563 + parser.getPositionDescription());
8564 } else if (codePathStr == null) {
8565 reportSettingsProblem(Log.WARN,
8566 "Error in package manager settings: <package> has no codePath at "
8567 + parser.getPositionDescription());
8568 } else if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008569 packageSetting = addPackageLP(name.intern(), realName,
8570 new File(codePathStr), new File(resourcePathStr),
8571 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8573 + ": userId=" + userId + " pkg=" + packageSetting);
8574 if (packageSetting == null) {
8575 reportSettingsProblem(Log.ERROR,
8576 "Failure adding uid " + userId
8577 + " while parsing settings at "
8578 + parser.getPositionDescription());
8579 } else {
8580 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8581 }
8582 } else if (sharedIdStr != null) {
8583 userId = sharedIdStr != null
8584 ? Integer.parseInt(sharedIdStr) : 0;
8585 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008586 packageSetting = new PendingPackage(name.intern(), realName,
8587 new File(codePathStr), new File(resourcePathStr),
8588 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008589 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8590 mPendingPackages.add((PendingPackage) packageSetting);
8591 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8592 + ": sharedUserId=" + userId + " pkg="
8593 + packageSetting);
8594 } else {
8595 reportSettingsProblem(Log.WARN,
8596 "Error in package manager settings: package "
8597 + name + " has bad sharedId " + sharedIdStr
8598 + " at " + parser.getPositionDescription());
8599 }
8600 } else {
8601 reportSettingsProblem(Log.WARN,
8602 "Error in package manager settings: package "
8603 + name + " has bad userId " + idStr + " at "
8604 + parser.getPositionDescription());
8605 }
8606 } catch (NumberFormatException e) {
8607 reportSettingsProblem(Log.WARN,
8608 "Error in package manager settings: package "
8609 + name + " has bad userId " + idStr + " at "
8610 + parser.getPositionDescription());
8611 }
8612 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008613 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02008614 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 final String enabledStr = parser.getAttributeValue(null, "enabled");
8616 if (enabledStr != null) {
8617 if (enabledStr.equalsIgnoreCase("true")) {
8618 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
8619 } else if (enabledStr.equalsIgnoreCase("false")) {
8620 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
8621 } else if (enabledStr.equalsIgnoreCase("default")) {
8622 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8623 } else {
8624 reportSettingsProblem(Log.WARN,
8625 "Error in package manager settings: package "
8626 + name + " has bad enabled value: " + idStr
8627 + " at " + parser.getPositionDescription());
8628 }
8629 } else {
8630 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8631 }
8632 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
8633 if (installStatusStr != null) {
8634 if (installStatusStr.equalsIgnoreCase("false")) {
8635 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
8636 } else {
8637 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
8638 }
8639 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008641 int outerDepth = parser.getDepth();
8642 int type;
8643 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8644 && (type != XmlPullParser.END_TAG
8645 || parser.getDepth() > outerDepth)) {
8646 if (type == XmlPullParser.END_TAG
8647 || type == XmlPullParser.TEXT) {
8648 continue;
8649 }
8650
8651 String tagName = parser.getName();
8652 if (tagName.equals("disabled-components")) {
8653 readDisabledComponentsLP(packageSetting, parser);
8654 } else if (tagName.equals("enabled-components")) {
8655 readEnabledComponentsLP(packageSetting, parser);
8656 } else if (tagName.equals("sigs")) {
8657 packageSetting.signatures.readXml(parser, mPastSignatures);
8658 } else if (tagName.equals("perms")) {
8659 readGrantedPermissionsLP(parser,
8660 packageSetting.loadedPermissions);
8661 packageSetting.permissionsFixed = true;
8662 } else {
8663 reportSettingsProblem(Log.WARN,
8664 "Unknown element under <package>: "
8665 + parser.getName());
8666 XmlUtils.skipCurrentTag(parser);
8667 }
8668 }
8669 } else {
8670 XmlUtils.skipCurrentTag(parser);
8671 }
8672 }
8673
8674 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
8675 XmlPullParser parser)
8676 throws IOException, XmlPullParserException {
8677 int outerDepth = parser.getDepth();
8678 int type;
8679 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8680 && (type != XmlPullParser.END_TAG
8681 || parser.getDepth() > outerDepth)) {
8682 if (type == XmlPullParser.END_TAG
8683 || type == XmlPullParser.TEXT) {
8684 continue;
8685 }
8686
8687 String tagName = parser.getName();
8688 if (tagName.equals("item")) {
8689 String name = parser.getAttributeValue(null, "name");
8690 if (name != null) {
8691 packageSetting.disabledComponents.add(name.intern());
8692 } else {
8693 reportSettingsProblem(Log.WARN,
8694 "Error in package manager settings: <disabled-components> has"
8695 + " no name at " + parser.getPositionDescription());
8696 }
8697 } else {
8698 reportSettingsProblem(Log.WARN,
8699 "Unknown element under <disabled-components>: "
8700 + parser.getName());
8701 }
8702 XmlUtils.skipCurrentTag(parser);
8703 }
8704 }
8705
8706 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
8707 XmlPullParser parser)
8708 throws IOException, XmlPullParserException {
8709 int outerDepth = parser.getDepth();
8710 int type;
8711 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8712 && (type != XmlPullParser.END_TAG
8713 || parser.getDepth() > outerDepth)) {
8714 if (type == XmlPullParser.END_TAG
8715 || type == XmlPullParser.TEXT) {
8716 continue;
8717 }
8718
8719 String tagName = parser.getName();
8720 if (tagName.equals("item")) {
8721 String name = parser.getAttributeValue(null, "name");
8722 if (name != null) {
8723 packageSetting.enabledComponents.add(name.intern());
8724 } else {
8725 reportSettingsProblem(Log.WARN,
8726 "Error in package manager settings: <enabled-components> has"
8727 + " no name at " + parser.getPositionDescription());
8728 }
8729 } else {
8730 reportSettingsProblem(Log.WARN,
8731 "Unknown element under <enabled-components>: "
8732 + parser.getName());
8733 }
8734 XmlUtils.skipCurrentTag(parser);
8735 }
8736 }
8737
8738 private void readSharedUserLP(XmlPullParser parser)
8739 throws XmlPullParserException, IOException {
8740 String name = null;
8741 String idStr = null;
8742 int pkgFlags = 0;
8743 SharedUserSetting su = null;
8744 try {
8745 name = parser.getAttributeValue(null, "name");
8746 idStr = parser.getAttributeValue(null, "userId");
8747 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8748 if ("true".equals(parser.getAttributeValue(null, "system"))) {
8749 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8750 }
8751 if (name == null) {
8752 reportSettingsProblem(Log.WARN,
8753 "Error in package manager settings: <shared-user> has no name at "
8754 + parser.getPositionDescription());
8755 } else if (userId == 0) {
8756 reportSettingsProblem(Log.WARN,
8757 "Error in package manager settings: shared-user "
8758 + name + " has bad userId " + idStr + " at "
8759 + parser.getPositionDescription());
8760 } else {
8761 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
8762 reportSettingsProblem(Log.ERROR,
8763 "Occurred while parsing settings at "
8764 + parser.getPositionDescription());
8765 }
8766 }
8767 } catch (NumberFormatException e) {
8768 reportSettingsProblem(Log.WARN,
8769 "Error in package manager settings: package "
8770 + name + " has bad userId " + idStr + " at "
8771 + parser.getPositionDescription());
8772 };
8773
8774 if (su != null) {
8775 int outerDepth = parser.getDepth();
8776 int type;
8777 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8778 && (type != XmlPullParser.END_TAG
8779 || parser.getDepth() > outerDepth)) {
8780 if (type == XmlPullParser.END_TAG
8781 || type == XmlPullParser.TEXT) {
8782 continue;
8783 }
8784
8785 String tagName = parser.getName();
8786 if (tagName.equals("sigs")) {
8787 su.signatures.readXml(parser, mPastSignatures);
8788 } else if (tagName.equals("perms")) {
8789 readGrantedPermissionsLP(parser, su.loadedPermissions);
8790 } else {
8791 reportSettingsProblem(Log.WARN,
8792 "Unknown element under <shared-user>: "
8793 + parser.getName());
8794 XmlUtils.skipCurrentTag(parser);
8795 }
8796 }
8797
8798 } else {
8799 XmlUtils.skipCurrentTag(parser);
8800 }
8801 }
8802
8803 private void readGrantedPermissionsLP(XmlPullParser parser,
8804 HashSet<String> outPerms) throws IOException, XmlPullParserException {
8805 int outerDepth = parser.getDepth();
8806 int type;
8807 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8808 && (type != XmlPullParser.END_TAG
8809 || parser.getDepth() > outerDepth)) {
8810 if (type == XmlPullParser.END_TAG
8811 || type == XmlPullParser.TEXT) {
8812 continue;
8813 }
8814
8815 String tagName = parser.getName();
8816 if (tagName.equals("item")) {
8817 String name = parser.getAttributeValue(null, "name");
8818 if (name != null) {
8819 outPerms.add(name.intern());
8820 } else {
8821 reportSettingsProblem(Log.WARN,
8822 "Error in package manager settings: <perms> has"
8823 + " no name at " + parser.getPositionDescription());
8824 }
8825 } else {
8826 reportSettingsProblem(Log.WARN,
8827 "Unknown element under <perms>: "
8828 + parser.getName());
8829 }
8830 XmlUtils.skipCurrentTag(parser);
8831 }
8832 }
8833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 private void readPreferredActivitiesLP(XmlPullParser parser)
8835 throws XmlPullParserException, IOException {
8836 int outerDepth = parser.getDepth();
8837 int type;
8838 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8839 && (type != XmlPullParser.END_TAG
8840 || parser.getDepth() > outerDepth)) {
8841 if (type == XmlPullParser.END_TAG
8842 || type == XmlPullParser.TEXT) {
8843 continue;
8844 }
8845
8846 String tagName = parser.getName();
8847 if (tagName.equals("item")) {
8848 PreferredActivity pa = new PreferredActivity(parser);
8849 if (pa.mParseError == null) {
8850 mPreferredActivities.addFilter(pa);
8851 } else {
8852 reportSettingsProblem(Log.WARN,
8853 "Error in package manager settings: <preferred-activity> "
8854 + pa.mParseError + " at "
8855 + parser.getPositionDescription());
8856 }
8857 } else {
8858 reportSettingsProblem(Log.WARN,
8859 "Unknown element under <preferred-activities>: "
8860 + parser.getName());
8861 XmlUtils.skipCurrentTag(parser);
8862 }
8863 }
8864 }
8865
8866 // Returns -1 if we could not find an available UserId to assign
8867 private int newUserIdLP(Object obj) {
8868 // Let's be stupidly inefficient for now...
8869 final int N = mUserIds.size();
8870 for (int i=0; i<N; i++) {
8871 if (mUserIds.get(i) == null) {
8872 mUserIds.set(i, obj);
8873 return FIRST_APPLICATION_UID + i;
8874 }
8875 }
8876
8877 // None left?
8878 if (N >= MAX_APPLICATION_UIDS) {
8879 return -1;
8880 }
8881
8882 mUserIds.add(obj);
8883 return FIRST_APPLICATION_UID + N;
8884 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008886 public PackageSetting getDisabledSystemPkg(String name) {
8887 synchronized(mPackages) {
8888 PackageSetting ps = mDisabledSysPackages.get(name);
8889 return ps;
8890 }
8891 }
8892
8893 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
8894 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
8895 if (Config.LOGV) {
8896 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
8897 + " componentName = " + componentInfo.name);
8898 Log.v(TAG, "enabledComponents: "
8899 + Arrays.toString(packageSettings.enabledComponents.toArray()));
8900 Log.v(TAG, "disabledComponents: "
8901 + Arrays.toString(packageSettings.disabledComponents.toArray()));
8902 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008903 if (packageSettings == null) {
8904 if (false) {
8905 Log.w(TAG, "WAITING FOR DEBUGGER");
8906 Debug.waitForDebugger();
8907 Log.i(TAG, "We will crash!");
8908 }
8909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
8911 || ((componentInfo.enabled
8912 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
8913 || (componentInfo.applicationInfo.enabled
8914 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
8915 && !packageSettings.disabledComponents.contains(componentInfo.name))
8916 || packageSettings.enabledComponents.contains(componentInfo.name));
8917 }
8918 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008919
8920 // ------- apps on sdcard specific code -------
8921 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08008922 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08008923 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008924 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008925 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008926
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008927 private String getEncryptKey() {
8928 try {
8929 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8930 if (sdEncKey == null) {
8931 sdEncKey = SystemKeyStore.getInstance().
8932 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
8933 if (sdEncKey == null) {
8934 Log.e(TAG, "Failed to create encryption keys");
8935 return null;
8936 }
8937 }
8938 return sdEncKey;
8939 } catch (NoSuchAlgorithmException nsae) {
8940 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
8941 return null;
8942 }
8943 }
8944
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008945 static String getTempContainerId() {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008946 String prefix = "smdl2tmp";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008947 int tmpIdx = 1;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008948 String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008949 if (list != null) {
8950 int idx = 0;
8951 int idList[] = new int[MAX_CONTAINERS];
8952 boolean neverFound = true;
8953 for (String name : list) {
8954 // Ignore null entries
8955 if (name == null) {
8956 continue;
8957 }
8958 int sidx = name.indexOf(prefix);
8959 if (sidx == -1) {
8960 // Not a temp file. just ignore
8961 continue;
8962 }
8963 String subStr = name.substring(sidx + prefix.length());
8964 idList[idx] = -1;
8965 if (subStr != null) {
8966 try {
8967 int cid = Integer.parseInt(subStr);
8968 idList[idx++] = cid;
8969 neverFound = false;
8970 } catch (NumberFormatException e) {
8971 }
8972 }
8973 }
8974 if (!neverFound) {
8975 // Sort idList
8976 Arrays.sort(idList);
8977 for (int j = 1; j <= idList.length; j++) {
8978 if (idList[j-1] != j) {
8979 tmpIdx = j;
8980 break;
8981 }
8982 }
8983 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008984 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008985 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008986 }
8987
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08008988 /*
8989 * Return true if PackageManager does have packages to be updated.
8990 */
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008991 public boolean updateExternalMediaStatus(final boolean mediaStatus) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08008992 final boolean ret;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008993 synchronized (mPackages) {
8994 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
8995 mediaStatus+", mMediaMounted=" + mMediaMounted);
8996 if (mediaStatus == mMediaMounted) {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08008997 return false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008998 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008999 mMediaMounted = mediaStatus;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009000 Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
9001 ret = appList != null && appList.size() > 0;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009002 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009003 // Queue up an async operation since the package installation may take a little while.
9004 mHandler.post(new Runnable() {
9005 public void run() {
9006 mHandler.removeCallbacks(this);
9007 updateExternalMediaStatusInner(mediaStatus, ret);
9008 }
9009 });
9010 return ret;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009011 }
9012
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009013 private void updateExternalMediaStatusInner(boolean mediaStatus,
9014 boolean sendUpdateBroadcast) {
9015 // If we are up here that means there are packages to be
9016 // enabled or disabled.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08009017 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009018 if (list == null || list.length == 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009019 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009020 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009021
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009022 int uidList[] = new int[list.length];
9023 int num = 0;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009024 HashSet<String> removeCids = new HashSet<String>();
9025 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
9026 /*HashMap<String, String> cidPathMap = new HashMap<String, String>();
9027 // Don't hold any locks when getting cache paths
9028 for (String cid : list) {
9029 String cpath = PackageHelper.getSdDir(cid);
9030 if (cpath == null) {
9031 removeCids.add(cid);
9032 } else {
9033 cidPathMap.put(cid, cpath);
9034 }
9035 }*/
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009036 synchronized (mPackages) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009037 for (String cid : list) {
9038 SdInstallArgs args = new SdInstallArgs(cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009039 if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
9040 boolean failed = true;
9041 try {
9042 String pkgName = args.getPackageName();
9043 if (pkgName == null) {
9044 continue;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009045 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009046 if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
9047 PackageSetting ps = mSettings.mPackages.get(pkgName);
9048 if (ps != null && ps.codePathString != null &&
9049 (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
9050 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
9051 " corresponds to pkg : " + pkgName +
9052 " at code path: " + ps.codePathString);
9053 // We do have a valid package installed on sdcard
9054 processCids.put(args, ps.codePathString);
9055 failed = false;
9056 int uid = ps.userId;
9057 if (uid != -1) {
9058 uidList[num++] = uid;
9059 }
9060 }
9061 } finally {
9062 if (failed) {
9063 // Stale container on sdcard. Just delete
9064 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
9065 removeCids.add(cid);
9066 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009067 }
9068 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009069 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009070 // Organize uids
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009071 int uidArr[] = null;
9072 if (num > 0) {
9073 // Sort uid list
9074 Arrays.sort(uidList, 0, num);
9075 // Throw away duplicates
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009076 uidArr = new int[num];
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009077 uidArr[0] = uidList[0];
9078 int di = 0;
9079 for (int i = 1; i < num; i++) {
9080 if (uidList[i-1] != uidList[i]) {
9081 uidArr[di++] = uidList[i];
9082 }
9083 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009084 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009085 // Process packages with valid entries.
9086 if (mediaStatus) {
9087 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
9088 loadMediaPackages(processCids, uidArr, sendUpdateBroadcast, removeCids);
9089 startCleaningPackages();
9090 } else {
9091 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
9092 unloadMediaPackages(processCids, uidArr, sendUpdateBroadcast);
9093 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009094 }
9095
9096 private void sendResourcesChangedBroadcast(boolean mediaStatus,
9097 ArrayList<String> pkgList, int uidArr[]) {
9098 int size = pkgList.size();
9099 if (size > 0) {
9100 // Send broadcasts here
9101 Bundle extras = new Bundle();
9102 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
9103 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009104 if (uidArr != null) {
9105 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
9106 }
9107 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
9108 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009109 sendPackageBroadcast(action, null, extras);
9110 }
9111 }
9112
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009113 /*
9114 * Look at potentially valid container ids from processCids
9115 * If package information doesn't match the one on record
9116 * or package scanning fails, the cid is added to list of
9117 * removeCids and cleaned up. Since cleaning up containers
9118 * involves destroying them, we do not want any parse
9119 * references to such stale containers. So force gc's
9120 * to avoid unnecessary crashes.
9121 */
9122 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
9123 int uidArr[], boolean sendUpdateBroadcast,
9124 HashSet<String> removeCids) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009125 ArrayList<String> pkgList = new ArrayList<String>();
9126 Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009127 boolean doGc = false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009128 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009129 String codePath = processCids.get(args);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009130 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : "
9131 + args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009132 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009133 try {
9134 // Make sure there are no container errors first.
9135 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED)
9136 != PackageManager.INSTALL_SUCCEEDED) {
9137 Log.e(TAG, "Failed to mount cid : " + args.cid +
9138 " when installing from sdcard");
9139 continue;
9140 }
9141 // Check code path here.
9142 if (codePath == null || !codePath.equals(args.getCodePath())) {
9143 Log.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+
9144 " does not match one in settings " + codePath);
9145 continue;
9146 }
9147 // Parse package
9148 int parseFlags = PackageParser.PARSE_CHATTY |
9149 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
9150 PackageParser pp = new PackageParser(codePath);
9151 pp.setSeparateProcesses(mSeparateProcesses);
9152 final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
9153 codePath, mMetrics, parseFlags);
9154 pp = null;
9155 doGc = true;
9156 // Check for parse errors
9157 if (pkg == null) {
9158 Log.e(TAG, "Parse error when installing install pkg : "
9159 + args.cid + " from " + args.cachePath);
9160 continue;
9161 }
9162 setApplicationInfoPaths(pkg, codePath, codePath);
9163 synchronized (mInstallLock) {
9164 // Scan the package
9165 if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
9166 synchronized (mPackages) {
9167 // Grant permissions
9168 grantPermissionsLP(pkg, false);
9169 // Persist settings
9170 mSettings.writeLP();
9171 retCode = PackageManager.INSTALL_SUCCEEDED;
9172 pkgList.add(pkg.packageName);
9173 // Post process args
9174 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
9175 }
9176 } else {
9177 Log.i(TAG, "Failed to install pkg: " +
9178 pkg.packageName + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009179 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009180 }
9181
9182 } finally {
9183 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
9184 // Don't destroy container here. Wait till gc clears things up.
9185 removeCids.add(args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009186 }
9187 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009188 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009189 // Send a broadcast to let everyone know we are done processing
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009190 if (sendUpdateBroadcast) {
9191 sendResourcesChangedBroadcast(true, pkgList, uidArr);
9192 }
9193 if (doGc) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009194 Runtime.getRuntime().gc();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009195 }
9196 // Delete any stale containers if needed.
9197 if (removeCids != null) {
9198 for (String cid : removeCids) {
9199 Log.i(TAG, "Destroying stale container : " + cid);
9200 PackageHelper.destroySdDir(cid);
9201 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009202 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009203 }
9204
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009205 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
9206 int uidArr[], boolean sendUpdateBroadcast) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009207 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009208 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009209 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009210 Set<SdInstallArgs> keys = processCids.keySet();
9211 for (SdInstallArgs args : keys) {
9212 String cid = args.cid;
9213 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009214 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009215 // Delete package internally
9216 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9217 synchronized (mInstallLock) {
9218 boolean res = deletePackageLI(pkgName, false,
9219 PackageManager.DONT_DELETE_DATA, outInfo);
9220 if (res) {
9221 pkgList.add(pkgName);
9222 } else {
9223 Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009224 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009225 }
9226 }
9227 }
9228 // Send broadcasts
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009229 if (sendUpdateBroadcast) {
9230 sendResourcesChangedBroadcast(false, pkgList, uidArr);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009231 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009232 // Force gc
9233 Runtime.getRuntime().gc();
9234 // Just unmount all valid containers.
9235 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009236 synchronized (mInstallLock) {
9237 args.doPostDeleteLI(false);
9238 }
9239 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009240 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009241
9242 public void movePackage(final String packageName,
9243 final IPackageMoveObserver observer, final int flags) {
9244 if (packageName == null) {
9245 return;
9246 }
9247 mContext.enforceCallingOrSelfPermission(
9248 android.Manifest.permission.MOVE_PACKAGE, null);
9249 int returnCode = PackageManager.MOVE_SUCCEEDED;
9250 int currFlags = 0;
9251 int newFlags = 0;
9252 synchronized (mPackages) {
9253 PackageParser.Package pkg = mPackages.get(packageName);
9254 if (pkg == null) {
9255 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9256 }
9257 // Disable moving fwd locked apps and system packages
9258 if (pkg.applicationInfo != null &&
9259 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
9260 Log.w(TAG, "Cannot move system application");
9261 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
9262 } else if (pkg.applicationInfo != null &&
9263 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
9264 Log.w(TAG, "Cannot move forward locked app.");
9265 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
9266 } else {
9267 // Find install location first
9268 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
9269 (flags & PackageManager.MOVE_INTERNAL) != 0) {
9270 Log.w(TAG, "Ambigous flags specified for move location.");
9271 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9272 } else {
9273 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
9274 PackageManager.INSTALL_EXTERNAL : 0;
9275 currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0 ?
9276 PackageManager.INSTALL_EXTERNAL : 0;
9277 if (newFlags == currFlags) {
9278 Log.w(TAG, "No move required. Trying to move to same location");
9279 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9280 }
9281 }
9282 }
9283 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
9284 processPendingMove(new MoveParams(null, observer, 0, null), returnCode);
9285 } else {
9286 Message msg = mHandler.obtainMessage(INIT_COPY);
9287 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
9288 pkg.applicationInfo.publicSourceDir);
9289 MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
9290 packageName);
9291 msg.obj = mp;
9292 mHandler.sendMessage(msg);
9293 }
9294 }
9295 }
9296
9297 private void processPendingMove(final MoveParams mp, final int currentStatus) {
9298 // Queue up an async operation since the package deletion may take a little while.
9299 mHandler.post(new Runnable() {
9300 public void run() {
9301 mHandler.removeCallbacks(this);
9302 int returnCode = currentStatus;
9303 boolean moveSucceeded = (returnCode == PackageManager.MOVE_SUCCEEDED);
9304 if (moveSucceeded) {
9305 int uid = -1;
9306 synchronized (mPackages) {
9307 uid = mPackages.get(mp.packageName).applicationInfo.uid;
9308 }
9309 ArrayList<String> pkgList = new ArrayList<String>();
9310 pkgList.add(mp.packageName);
9311 int uidArr[] = new int[] { uid };
9312 // Send resources unavailable broadcast
9313 sendResourcesChangedBroadcast(false, pkgList, uidArr);
9314
9315 // Update package code and resource paths
9316 synchronized (mPackages) {
9317 PackageParser.Package pkg = mPackages.get(mp.packageName);
9318 if (pkg != null) {
9319 String oldCodePath = pkg.mPath;
9320 String newCodePath = mp.targetArgs.getCodePath();
9321 String newResPath = mp.targetArgs.getResourcePath();
9322 pkg.mPath = newCodePath;
9323 // Move dex files around
9324 if (moveDexFiles(pkg)
9325 != PackageManager.INSTALL_SUCCEEDED) {
9326 // Moving of dex files failed. Set
9327 // error code and abort move.
9328 pkg.mPath = pkg.mScanPath;
9329 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9330 moveSucceeded = false;
9331 } else {
9332 pkg.mScanPath = newCodePath;
9333 pkg.applicationInfo.sourceDir = newCodePath;
9334 pkg.applicationInfo.publicSourceDir = newResPath;
9335 PackageSetting ps = (PackageSetting) pkg.mExtras;
9336 ps.codePath = new File(pkg.applicationInfo.sourceDir);
9337 ps.codePathString = ps.codePath.getPath();
9338 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
9339 ps.resourcePathString = ps.resourcePath.getPath();
9340 // Set the application info flag correctly.
9341 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
9342 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_ON_SDCARD;
9343 } else {
9344 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_ON_SDCARD;
9345 }
9346 ps.setFlags(pkg.applicationInfo.flags);
9347 mAppDirs.remove(oldCodePath);
9348 mAppDirs.put(newCodePath, pkg);
9349 // Persist settings
9350 mSettings.writeLP();
9351 }
9352 }
9353 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009354 // Send resources available broadcast
9355 sendResourcesChangedBroadcast(true, pkgList, uidArr);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009356 }
9357 if (!moveSucceeded){
9358 // Clean up failed installation
9359 if (mp.targetArgs != null) {
9360 mp.targetArgs.doPostInstall(
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009361 returnCode);
9362 }
9363 } else {
9364 // Force a gc to clear things up.
9365 Runtime.getRuntime().gc();
9366 // Delete older code
9367 synchronized (mInstallLock) {
9368 mp.srcArgs.doPostDeleteLI(true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009369 }
9370 }
9371 IPackageMoveObserver observer = mp.observer;
9372 if (observer != null) {
9373 try {
9374 observer.packageMoved(mp.packageName, returnCode);
9375 } catch (RemoteException e) {
9376 Log.i(TAG, "Observer no longer exists.");
9377 }
9378 }
9379 }
9380 });
9381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009382}