blob: 4326efcdcefb269e3659321787e11773f19d1bac [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;
Tom Taylord4a47292009-12-21 13:59:18 -080021import com.android.common.FastXmlSerializer;
22import com.android.common.XmlUtils;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080023import com.android.internal.content.PackageHelper;
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070036import android.content.IntentSender;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080037import android.content.ServiceConnection;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070038import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.content.pm.ActivityInfo;
40import android.content.pm.ApplicationInfo;
41import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070042import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.pm.IPackageDataObserver;
44import android.content.pm.IPackageDeleteObserver;
45import android.content.pm.IPackageInstallObserver;
46import android.content.pm.IPackageManager;
47import android.content.pm.IPackageStatsObserver;
48import android.content.pm.InstrumentationInfo;
49import android.content.pm.PackageInfo;
50import android.content.pm.PackageManager;
51import android.content.pm.PackageStats;
52import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
53import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
54import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
55import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
56import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
57import android.content.pm.PackageParser;
58import android.content.pm.PermissionInfo;
59import android.content.pm.PermissionGroupInfo;
60import android.content.pm.ProviderInfo;
61import android.content.pm.ResolveInfo;
62import android.content.pm.ServiceInfo;
63import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.net.Uri;
65import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070066import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080068import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080070import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070071import android.os.Looper;
72import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.Parcel;
74import android.os.RemoteException;
75import android.os.Environment;
76import android.os.FileObserver;
77import android.os.FileUtils;
78import android.os.Handler;
San Mehatb1043402010-02-05 08:26:50 -080079import android.os.storage.StorageResultCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.ParcelFileDescriptor;
81import android.os.Process;
82import android.os.ServiceManager;
83import android.os.SystemClock;
84import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080085import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.util.*;
87import android.view.Display;
88import android.view.WindowManager;
89
90import java.io.File;
91import java.io.FileDescriptor;
92import java.io.FileInputStream;
93import java.io.FileNotFoundException;
94import java.io.FileOutputStream;
95import java.io.FileReader;
96import java.io.FilenameFilter;
97import java.io.IOException;
98import java.io.InputStream;
99import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800100import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800101import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import java.util.ArrayList;
103import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700104import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105import java.util.Collections;
106import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800107import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.util.Enumeration;
109import java.util.HashMap;
110import java.util.HashSet;
111import java.util.Iterator;
112import java.util.List;
113import java.util.Map;
114import java.util.Set;
115import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800116import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.util.zip.ZipFile;
118import java.util.zip.ZipOutputStream;
119
120class PackageManagerService extends IPackageManager.Stub {
121 private static final String TAG = "PackageManager";
122 private static final boolean DEBUG_SETTINGS = false;
123 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800124 private static final boolean DEBUG_UPGRADE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125
126 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
127 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400128 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final int FIRST_APPLICATION_UID =
130 Process.FIRST_APPLICATION_UID;
131 private static final int MAX_APPLICATION_UIDS = 1000;
132
133 private static final boolean SHOW_INFO = false;
134
135 private static final boolean GET_CERTIFICATES = true;
136
Oscar Montemayora8529f62009-11-18 10:14:20 -0800137 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 private static final int REMOVE_EVENTS =
140 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
141 private static final int ADD_EVENTS =
142 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
143
144 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
145
146 static final int SCAN_MONITOR = 1<<0;
147 static final int SCAN_NO_DEX = 1<<1;
148 static final int SCAN_FORCE_DEX = 1<<2;
149 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800150 static final int SCAN_NEW_INSTALL = 1<<4;
151 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800153 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
154 "com.android.defcontainer",
155 "com.android.defcontainer.DefaultContainerService");
156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
158 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700159 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160
Dianne Hackborn851a5412009-05-08 12:06:44 -0700161 final int mSdkVersion = Build.VERSION.SDK_INT;
162 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
163 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 final Context mContext;
166 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700167 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 final DisplayMetrics mMetrics;
169 final int mDefParseFlags;
170 final String[] mSeparateProcesses;
171
172 // This is where all application persistent data goes.
173 final File mAppDataDir;
174
Oscar Montemayora8529f62009-11-18 10:14:20 -0800175 // If Encrypted File System feature is enabled, all application persistent data
176 // should go here instead.
177 final File mSecureAppDataDir;
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 // This is the object monitoring the framework dir.
180 final FileObserver mFrameworkInstallObserver;
181
182 // This is the object monitoring the system app dir.
183 final FileObserver mSystemInstallObserver;
184
185 // This is the object monitoring mAppInstallDir.
186 final FileObserver mAppInstallObserver;
187
188 // This is the object monitoring mDrmAppPrivateInstallDir.
189 final FileObserver mDrmAppInstallObserver;
190
191 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
192 // LOCK HELD. Can be called with mInstallLock held.
193 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 final File mFrameworkDir;
196 final File mSystemAppDir;
197 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700198 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
200 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
201 // apps.
202 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // Lock for state used when installing and doing other long running
207 // operations. Methods that must be called with this lock held have
208 // the prefix "LI".
209 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // These are the directories in the 3rd party applications installed dir
212 // that we have currently loaded packages from. Keys are the application's
213 // installed zip file (absolute codePath), and values are Package.
214 final HashMap<String, PackageParser.Package> mAppDirs =
215 new HashMap<String, PackageParser.Package>();
216
217 // Information for the parser to write more useful error messages.
218 File mScanningPath;
219 int mLastScanError;
220
221 final int[] mOutPermissions = new int[3];
222
223 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 // Keys are String (package name), values are Package. This also serves
226 // as the lock for the global state. Methods that must be called with
227 // this lock held have the prefix "LP".
228 final HashMap<String, PackageParser.Package> mPackages =
229 new HashMap<String, PackageParser.Package>();
230
231 final Settings mSettings;
232 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233
234 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
235 int[] mGlobalGids;
236
237 // These are the built-in uid -> permission mappings that were read from the
238 // etc/permissions.xml file.
239 final SparseArray<HashSet<String>> mSystemPermissions =
240 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 // These are the built-in shared libraries that were read from the
243 // etc/permissions.xml file.
244 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800245
Dianne Hackborn49237342009-08-27 20:08:01 -0700246 // Temporary for building the final shared libraries for an .apk.
247 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800248
Dianne Hackborn49237342009-08-27 20:08:01 -0700249 // These are the features this devices supports that were read from the
250 // etc/permissions.xml file.
251 final HashMap<String, FeatureInfo> mAvailableFeatures =
252 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 // All available activities, for your resolving pleasure.
255 final ActivityIntentResolver mActivities =
256 new ActivityIntentResolver();
257
258 // All available receivers, for your resolving pleasure.
259 final ActivityIntentResolver mReceivers =
260 new ActivityIntentResolver();
261
262 // All available services, for your resolving pleasure.
263 final ServiceIntentResolver mServices = new ServiceIntentResolver();
264
265 // Keys are String (provider class name), values are Provider.
266 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
267 new HashMap<ComponentName, PackageParser.Provider>();
268
269 // Mapping from provider base names (first directory in content URI codePath)
270 // to the provider information.
271 final HashMap<String, PackageParser.Provider> mProviders =
272 new HashMap<String, PackageParser.Provider>();
273
274 // Mapping from instrumentation class names to info about them.
275 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
276 new HashMap<ComponentName, PackageParser.Instrumentation>();
277
278 // Mapping from permission names to info about them.
279 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
280 new HashMap<String, PackageParser.PermissionGroup>();
281
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800282 // Packages whose data we have transfered into another package, thus
283 // should no longer exist.
284 final HashSet<String> mTransferedPackages = new HashSet<String>();
285
Dianne Hackborn854060af2009-07-09 18:14:31 -0700286 // Broadcast actions that are only available to the system.
287 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 boolean mSystemReady;
290 boolean mSafeMode;
291 boolean mHasSystemUidErrors;
292
293 ApplicationInfo mAndroidApplication;
294 final ActivityInfo mResolveActivity = new ActivityInfo();
295 final ResolveInfo mResolveInfo = new ResolveInfo();
296 ComponentName mResolveComponentName;
297 PackageParser.Package mPlatformPackage;
298
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700299 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800300 final HashMap<String, ArrayList<String>> mPendingBroadcasts
301 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700302 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800303 static final int MCS_BOUND = 3;
304 static final int END_COPY = 4;
305 static final int INIT_COPY = 5;
306 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800307 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800308 static final int FIND_INSTALL_LOC = 8;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700309 // Delay time in millisecs
310 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800311 private ServiceConnection mDefContainerConn = new ServiceConnection() {
312 public void onServiceConnected(ComponentName name, IBinder service) {
313 IMediaContainerService imcs =
314 IMediaContainerService.Stub.asInterface(service);
315 Message msg = mHandler.obtainMessage(MCS_BOUND, imcs);
316 mHandler.sendMessage(msg);
317 }
318
319 public void onServiceDisconnected(ComponentName name) {
320 }
321 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700322
323 class PackageHandler extends Handler {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800324 final ArrayList<InstallParams> mPendingInstalls =
325 new ArrayList<InstallParams>();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800326 // Service Connection to remote media container service to copy
327 // package uri's from external media onto secure containers
328 // or internal storage.
329 private IMediaContainerService mContainerService = null;
330
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700331 PackageHandler(Looper looper) {
332 super(looper);
333 }
334 public void handleMessage(Message msg) {
335 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800336 case INIT_COPY: {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800337 InstallParams params = (InstallParams) msg.obj;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800338 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800339 if (mContainerService != null) {
340 // No need to add to pending list. Use remote stub directly
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800341 handleStartCopy(params);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800342 } else {
343 if (mContext.bindService(service, mDefContainerConn,
344 Context.BIND_AUTO_CREATE)) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800345 mPendingInstalls.add(params);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800346 } else {
347 Log.e(TAG, "Failed to bind to media container service");
348 // Indicate install failure TODO add new error code
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800349 processPendingInstall(createInstallArgs(params),
350 PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800351 }
352 }
353 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800354 }
355 case MCS_BOUND: {
356 // Initialize mContainerService if needed.
357 if (msg.obj != null) {
358 mContainerService = (IMediaContainerService) msg.obj;
359 }
360 if (mPendingInstalls.size() > 0) {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800361 InstallParams params = mPendingInstalls.remove(0);
362 if (params != null) {
363 handleStartCopy(params);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800364 }
365 }
366 break;
367 }
368 case MCS_UNBIND : {
369 if (mPendingInstalls.size() == 0) {
370 mContext.unbindService(mDefContainerConn);
371 mContainerService = null;
372 }
373 break;
374 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700375 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800376 String packages[];
377 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700378 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700379 int uids[];
380 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800381 if (mPendingBroadcasts == null) {
382 return;
383 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700384 size = mPendingBroadcasts.size();
385 if (size <= 0) {
386 // Nothing to be done. Just return
387 return;
388 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800389 packages = new String[size];
390 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700391 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800392 Iterator<HashMap.Entry<String, ArrayList<String>>>
393 it = mPendingBroadcasts.entrySet().iterator();
394 int i = 0;
395 while (it.hasNext() && i < size) {
396 HashMap.Entry<String, ArrayList<String>> ent = it.next();
397 packages[i] = ent.getKey();
398 components[i] = ent.getValue();
399 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700400 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800401 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700402 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800403 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700404 mPendingBroadcasts.clear();
405 }
406 // Send broadcasts
407 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800408 sendPackageChangedBroadcast(packages[i], true,
409 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700410 }
411 break;
412 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800413 case START_CLEANING_PACKAGE: {
414 String packageName = (String)msg.obj;
415 synchronized (mPackages) {
416 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
417 mSettings.mPackagesToBeCleaned.add(packageName);
418 }
419 }
420 startCleaningPackages();
421 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700422 }
423 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800424
425 // Utility method to initiate copying apk via media
426 // container service.
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800427 private void handleStartCopy(InstallParams params) {
428 int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
429 if (mContainerService != null) {
430 // Remote call to find out default install location
431 int loc = params.getInstallLocation(mContainerService);
432 // Use install location to create InstallArgs and temporary
433 // install location
434 if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
435 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
436 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
437 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
438 } else {
439 if ((params.flags & PackageManager.INSTALL_EXTERNAL) == 0){
440 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
441 // Set the flag to install on external media.
442 params.flags |= PackageManager.INSTALL_EXTERNAL;
443 } else {
444 // Make sure the flag for installing on external
445 // media is unset
446 params.flags &= ~PackageManager.INSTALL_EXTERNAL;
447 }
448 }
449 // Disable forward locked apps on sdcard.
450 if ((params.flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 &&
451 (params.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
452 // Make sure forward locked apps can only be installed
453 // on internal storage
454 Log.w(TAG, "Cannot install protected apps on sdcard");
455 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
456 } else {
457 ret = PackageManager.INSTALL_SUCCEEDED;
458 }
459 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800460 }
461 mHandler.sendEmptyMessage(MCS_UNBIND);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800462 // Create the file args now.
463 InstallArgs args = createInstallArgs(params);
464 if (ret == PackageManager.INSTALL_SUCCEEDED) {
465 // Create copy only if we are not in an erroneous state.
466 args.createCopyFile();
467 // Remote call to initiate copy
468 ret = args.copyApk(mContainerService);
469 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800470 processPendingInstall(args, ret);
471 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700472 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800473
474 static boolean installOnSd(int flags) {
475 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800476 ((flags & PackageManager.INSTALL_EXTERNAL) == 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800477 return false;
478 }
479 return true;
480 }
481
482 static boolean isFwdLocked(int flags) {
483 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
484 return true;
485 }
486 return false;
487 }
488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 public static final IPackageManager main(Context context, boolean factoryTest) {
490 PackageManagerService m = new PackageManagerService(context, factoryTest);
491 ServiceManager.addService("package", m);
492 return m;
493 }
494
495 static String[] splitString(String str, char sep) {
496 int count = 1;
497 int i = 0;
498 while ((i=str.indexOf(sep, i)) >= 0) {
499 count++;
500 i++;
501 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 String[] res = new String[count];
504 i=0;
505 count = 0;
506 int lastI=0;
507 while ((i=str.indexOf(sep, i)) >= 0) {
508 res[count] = str.substring(lastI, i);
509 count++;
510 i++;
511 lastI = i;
512 }
513 res[count] = str.substring(lastI, str.length());
514 return res;
515 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800518 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 if (mSdkVersion <= 0) {
522 Log.w(TAG, "**** ro.build.version.sdk not set!");
523 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 mContext = context;
526 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700527 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 mMetrics = new DisplayMetrics();
529 mSettings = new Settings();
530 mSettings.addSharedUserLP("android.uid.system",
531 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
532 mSettings.addSharedUserLP("android.uid.phone",
533 MULTIPLE_APPLICATION_UIDS
534 ? RADIO_UID : FIRST_APPLICATION_UID,
535 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400536 mSettings.addSharedUserLP("android.uid.log",
537 MULTIPLE_APPLICATION_UIDS
538 ? LOG_UID : FIRST_APPLICATION_UID,
539 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540
541 String separateProcesses = SystemProperties.get("debug.separate_processes");
542 if (separateProcesses != null && separateProcesses.length() > 0) {
543 if ("*".equals(separateProcesses)) {
544 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
545 mSeparateProcesses = null;
546 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
547 } else {
548 mDefParseFlags = 0;
549 mSeparateProcesses = separateProcesses.split(",");
550 Log.w(TAG, "Running with debug.separate_processes: "
551 + separateProcesses);
552 }
553 } else {
554 mDefParseFlags = 0;
555 mSeparateProcesses = null;
556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 Installer installer = new Installer();
559 // Little hacky thing to check if installd is here, to determine
560 // whether we are running on the simulator and thus need to take
561 // care of building the /data file structure ourself.
562 // (apparently the sim now has a working installer)
563 if (installer.ping() && Process.supportsProcesses()) {
564 mInstaller = installer;
565 } else {
566 mInstaller = null;
567 }
568
569 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
570 Display d = wm.getDefaultDisplay();
571 d.getMetrics(mMetrics);
572
573 synchronized (mInstallLock) {
574 synchronized (mPackages) {
575 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700576 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 File dataDir = Environment.getDataDirectory();
579 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800580 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
582
583 if (mInstaller == null) {
584 // Make sure these dirs exist, when we are running in
585 // the simulator.
586 // Make a wide-open directory for random misc stuff.
587 File miscDir = new File(dataDir, "misc");
588 miscDir.mkdirs();
589 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800590 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 mDrmAppPrivateInstallDir.mkdirs();
592 }
593
594 readPermissions();
595
596 mRestoredSettings = mSettings.readLP();
597 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800598
599 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800601
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800602 // Set flag to monitor and not change apk file paths when
603 // scanning install directories.
604 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700605 if (mNoDexOpt) {
606 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800607 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700608 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700613 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700616 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 /**
619 * Out of paranoia, ensure that everything in the boot class
620 * path has been dexed.
621 */
622 String bootClassPath = System.getProperty("java.boot.class.path");
623 if (bootClassPath != null) {
624 String[] paths = splitString(bootClassPath, ':');
625 for (int i=0; i<paths.length; i++) {
626 try {
627 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
628 libFiles.add(paths[i]);
629 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700630 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 }
632 } catch (FileNotFoundException e) {
633 Log.w(TAG, "Boot class path not found: " + paths[i]);
634 } catch (IOException e) {
635 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
636 }
637 }
638 } else {
639 Log.w(TAG, "No BOOTCLASSPATH found!");
640 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 /**
643 * Also ensure all external libraries have had dexopt run on them.
644 */
645 if (mSharedLibraries.size() > 0) {
646 Iterator<String> libs = mSharedLibraries.values().iterator();
647 while (libs.hasNext()) {
648 String lib = libs.next();
649 try {
650 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
651 libFiles.add(lib);
652 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700653 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 }
655 } catch (FileNotFoundException e) {
656 Log.w(TAG, "Library not found: " + lib);
657 } catch (IOException e) {
658 Log.w(TAG, "Exception reading library: " + lib, e);
659 }
660 }
661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 // Gross hack for now: we know this file doesn't contain any
664 // code, so don't dexopt it to avoid the resulting log spew.
665 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 /**
668 * And there are a number of commands implemented in Java, which
669 * we currently need to do the dexopt on so that they can be
670 * run from a non-root shell.
671 */
672 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700673 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 for (int i=0; i<frameworkFiles.length; i++) {
675 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
676 String path = libPath.getPath();
677 // Skip the file if we alrady did it.
678 if (libFiles.contains(path)) {
679 continue;
680 }
681 // Skip the file if it is not a type we want to dexopt.
682 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
683 continue;
684 }
685 try {
686 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
687 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700688 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 }
690 } catch (FileNotFoundException e) {
691 Log.w(TAG, "Jar not found: " + path);
692 } catch (IOException e) {
693 Log.w(TAG, "Exception reading jar: " + path, e);
694 }
695 }
696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800697
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700698 if (didDexOpt) {
699 // If we had to do a dexopt of one of the previous
700 // things, then something on the system has changed.
701 // Consider this significant, and wipe away all other
702 // existing dexopt files to ensure we don't leave any
703 // dangling around.
704 String[] files = mDalvikCacheDir.list();
705 if (files != null) {
706 for (int i=0; i<files.length; i++) {
707 String fn = files[i];
708 if (fn.startsWith("data@app@")
709 || fn.startsWith("data@app-private@")) {
710 Log.i(TAG, "Pruning dalvik file: " + fn);
711 (new File(mDalvikCacheDir, fn)).delete();
712 }
713 }
714 }
715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800717
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800718 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 mFrameworkInstallObserver = new AppDirObserver(
720 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
721 mFrameworkInstallObserver.startWatching();
722 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800723 scanMode | SCAN_NO_DEX);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800724
725 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
727 mSystemInstallObserver = new AppDirObserver(
728 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
729 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800730 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800731
732 if (mInstaller != null) {
733 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
734 mInstaller.moveFiles();
735 }
736
737 // Prune any system packages that no longer exist.
738 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
739 while (psit.hasNext()) {
740 PackageSetting ps = psit.next();
741 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800742 && !mPackages.containsKey(ps.name)
743 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800744 psit.remove();
745 String msg = "System package " + ps.name
746 + " no longer exists; wiping its data";
747 reportSettingsProblem(Log.WARN, msg);
748 if (mInstaller != null) {
749 // XXX how to set useEncryptedFSDir for packages that
750 // are not encrypted?
751 mInstaller.remove(ps.name, true);
752 }
753 }
754 }
755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 mAppInstallDir = new File(dataDir, "app");
757 if (mInstaller == null) {
758 // Make sure these dirs exist, when we are running in
759 // the simulator.
760 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
761 }
762 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800763 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 //clean up list
765 for(int i = 0; i < deletePkgsList.size(); i++) {
766 //clean up here
767 cleanupInstallFailedPackage(deletePkgsList.get(i));
768 }
769 //delete tmp files
770 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800771
772 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 SystemClock.uptimeMillis());
774 mAppInstallObserver = new AppDirObserver(
775 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
776 mAppInstallObserver.startWatching();
777 scanDirLI(mAppInstallDir, 0, scanMode);
778
779 mDrmAppInstallObserver = new AppDirObserver(
780 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
781 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800782 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800784 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 SystemClock.uptimeMillis());
786 Log.i(TAG, "Time to scan packages: "
787 + ((SystemClock.uptimeMillis()-startTime)/1000f)
788 + " seconds");
789
790 updatePermissionsLP();
791
792 mSettings.writeLP();
793
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800794 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 // Now after opening every single application zip, make sure they
798 // are all flushed. Not really needed, but keeps things nice and
799 // tidy.
800 Runtime.getRuntime().gc();
801 } // synchronized (mPackages)
802 } // synchronized (mInstallLock)
803 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 @Override
806 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
807 throws RemoteException {
808 try {
809 return super.onTransact(code, data, reply, flags);
810 } catch (RuntimeException e) {
811 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
812 Log.e(TAG, "Package Manager Crash", e);
813 }
814 throw e;
815 }
816 }
817
Dianne Hackborne6620b22010-01-22 14:46:21 -0800818 void cleanupInstallFailedPackage(PackageSetting ps) {
819 Log.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 if (mInstaller != null) {
Kenny Rootbdbc9252010-01-28 12:03:49 -0800821 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
822 int retCode = mInstaller.remove(ps.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 if (retCode < 0) {
824 Log.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800825 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 }
827 } else {
828 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800829 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 File dataDir = new File(pkg.applicationInfo.dataDir);
831 dataDir.delete();
832 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800833 if (ps.codePath != null) {
834 if (!ps.codePath.delete()) {
835 Log.w(TAG, "Unable to remove old code file: " + ps.codePath);
836 }
837 }
838 if (ps.resourcePath != null) {
839 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
840 Log.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
841 }
842 }
843 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845
846 void readPermissions() {
847 // Read permissions from .../etc/permission directory.
848 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
849 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
850 Log.w(TAG, "No directory " + libraryDir + ", skipping");
851 return;
852 }
853 if (!libraryDir.canRead()) {
854 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
855 return;
856 }
857
858 // Iterate over the files in the directory and scan .xml files
859 for (File f : libraryDir.listFiles()) {
860 // We'll read platform.xml last
861 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
862 continue;
863 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 if (!f.getPath().endsWith(".xml")) {
866 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
867 continue;
868 }
869 if (!f.canRead()) {
870 Log.w(TAG, "Permissions library file " + f + " cannot be read");
871 continue;
872 }
873
874 readPermissionsFromXml(f);
875 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
878 final File permFile = new File(Environment.getRootDirectory(),
879 "etc/permissions/platform.xml");
880 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800881
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700882 StringBuilder sb = new StringBuilder(128);
883 sb.append("Libs:");
884 Iterator<String> it = mSharedLibraries.keySet().iterator();
885 while (it.hasNext()) {
886 sb.append(' ');
887 String name = it.next();
888 sb.append(name);
889 sb.append(':');
890 sb.append(mSharedLibraries.get(name));
891 }
892 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800893
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700894 sb.setLength(0);
895 sb.append("Features:");
896 it = mAvailableFeatures.keySet().iterator();
897 while (it.hasNext()) {
898 sb.append(' ');
899 sb.append(it.next());
900 }
901 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800903
904 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 FileReader permReader = null;
906 try {
907 permReader = new FileReader(permFile);
908 } catch (FileNotFoundException e) {
909 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
910 return;
911 }
912
913 try {
914 XmlPullParser parser = Xml.newPullParser();
915 parser.setInput(permReader);
916
917 XmlUtils.beginDocument(parser, "permissions");
918
919 while (true) {
920 XmlUtils.nextElement(parser);
921 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
922 break;
923 }
924
925 String name = parser.getName();
926 if ("group".equals(name)) {
927 String gidStr = parser.getAttributeValue(null, "gid");
928 if (gidStr != null) {
929 int gid = Integer.parseInt(gidStr);
930 mGlobalGids = appendInt(mGlobalGids, gid);
931 } else {
932 Log.w(TAG, "<group> without gid at "
933 + parser.getPositionDescription());
934 }
935
936 XmlUtils.skipCurrentTag(parser);
937 continue;
938 } else if ("permission".equals(name)) {
939 String perm = parser.getAttributeValue(null, "name");
940 if (perm == null) {
941 Log.w(TAG, "<permission> without name at "
942 + parser.getPositionDescription());
943 XmlUtils.skipCurrentTag(parser);
944 continue;
945 }
946 perm = perm.intern();
947 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 } else if ("assign-permission".equals(name)) {
950 String perm = parser.getAttributeValue(null, "name");
951 if (perm == null) {
952 Log.w(TAG, "<assign-permission> without name at "
953 + parser.getPositionDescription());
954 XmlUtils.skipCurrentTag(parser);
955 continue;
956 }
957 String uidStr = parser.getAttributeValue(null, "uid");
958 if (uidStr == null) {
959 Log.w(TAG, "<assign-permission> without uid at "
960 + parser.getPositionDescription());
961 XmlUtils.skipCurrentTag(parser);
962 continue;
963 }
964 int uid = Process.getUidForName(uidStr);
965 if (uid < 0) {
966 Log.w(TAG, "<assign-permission> with unknown uid \""
967 + uidStr + "\" at "
968 + parser.getPositionDescription());
969 XmlUtils.skipCurrentTag(parser);
970 continue;
971 }
972 perm = perm.intern();
973 HashSet<String> perms = mSystemPermissions.get(uid);
974 if (perms == null) {
975 perms = new HashSet<String>();
976 mSystemPermissions.put(uid, perms);
977 }
978 perms.add(perm);
979 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981 } else if ("library".equals(name)) {
982 String lname = parser.getAttributeValue(null, "name");
983 String lfile = parser.getAttributeValue(null, "file");
984 if (lname == null) {
985 Log.w(TAG, "<library> without name at "
986 + parser.getPositionDescription());
987 } else if (lfile == null) {
988 Log.w(TAG, "<library> without file at "
989 + parser.getPositionDescription());
990 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700991 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700992 mSharedLibraries.put(lname, lfile);
993 }
994 XmlUtils.skipCurrentTag(parser);
995 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800996
Dianne Hackborn49237342009-08-27 20:08:01 -0700997 } else if ("feature".equals(name)) {
998 String fname = parser.getAttributeValue(null, "name");
999 if (fname == null) {
1000 Log.w(TAG, "<feature> without name at "
1001 + parser.getPositionDescription());
1002 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001003 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001004 FeatureInfo fi = new FeatureInfo();
1005 fi.name = fname;
1006 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 }
1008 XmlUtils.skipCurrentTag(parser);
1009 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 } else {
1012 XmlUtils.skipCurrentTag(parser);
1013 continue;
1014 }
1015
1016 }
1017 } catch (XmlPullParserException e) {
1018 Log.w(TAG, "Got execption parsing permissions.", e);
1019 } catch (IOException e) {
1020 Log.w(TAG, "Got execption parsing permissions.", e);
1021 }
1022 }
1023
1024 void readPermission(XmlPullParser parser, String name)
1025 throws IOException, XmlPullParserException {
1026
1027 name = name.intern();
1028
1029 BasePermission bp = mSettings.mPermissions.get(name);
1030 if (bp == null) {
1031 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1032 mSettings.mPermissions.put(name, bp);
1033 }
1034 int outerDepth = parser.getDepth();
1035 int type;
1036 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1037 && (type != XmlPullParser.END_TAG
1038 || parser.getDepth() > outerDepth)) {
1039 if (type == XmlPullParser.END_TAG
1040 || type == XmlPullParser.TEXT) {
1041 continue;
1042 }
1043
1044 String tagName = parser.getName();
1045 if ("group".equals(tagName)) {
1046 String gidStr = parser.getAttributeValue(null, "gid");
1047 if (gidStr != null) {
1048 int gid = Process.getGidForName(gidStr);
1049 bp.gids = appendInt(bp.gids, gid);
1050 } else {
1051 Log.w(TAG, "<group> without gid at "
1052 + parser.getPositionDescription());
1053 }
1054 }
1055 XmlUtils.skipCurrentTag(parser);
1056 }
1057 }
1058
1059 static int[] appendInt(int[] cur, int val) {
1060 if (cur == null) {
1061 return new int[] { val };
1062 }
1063 final int N = cur.length;
1064 for (int i=0; i<N; i++) {
1065 if (cur[i] == val) {
1066 return cur;
1067 }
1068 }
1069 int[] ret = new int[N+1];
1070 System.arraycopy(cur, 0, ret, 0, N);
1071 ret[N] = val;
1072 return ret;
1073 }
1074
1075 static int[] appendInts(int[] cur, int[] add) {
1076 if (add == null) return cur;
1077 if (cur == null) return add;
1078 final int N = add.length;
1079 for (int i=0; i<N; i++) {
1080 cur = appendInt(cur, add[i]);
1081 }
1082 return cur;
1083 }
1084
1085 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001086 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1087 // The package has been uninstalled but has retained data and resources.
1088 return PackageParser.generatePackageInfo(p, null, flags);
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 final PackageSetting ps = (PackageSetting)p.mExtras;
1091 if (ps == null) {
1092 return null;
1093 }
1094 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1095 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1096 }
1097
1098 public PackageInfo getPackageInfo(String packageName, int flags) {
1099 synchronized (mPackages) {
1100 PackageParser.Package p = mPackages.get(packageName);
1101 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001102 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 + ": " + p);
1104 if (p != null) {
1105 return generatePackageInfo(p, flags);
1106 }
1107 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1108 return generatePackageInfoFromSettingsLP(packageName, flags);
1109 }
1110 }
1111 return null;
1112 }
1113
Dianne Hackborn47096932010-02-11 15:57:09 -08001114 public String[] currentToCanonicalPackageNames(String[] names) {
1115 String[] out = new String[names.length];
1116 synchronized (mPackages) {
1117 for (int i=names.length-1; i>=0; i--) {
1118 PackageSetting ps = mSettings.mPackages.get(names[i]);
1119 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1120 }
1121 }
1122 return out;
1123 }
1124
1125 public String[] canonicalToCurrentPackageNames(String[] names) {
1126 String[] out = new String[names.length];
1127 synchronized (mPackages) {
1128 for (int i=names.length-1; i>=0; i--) {
1129 String cur = mSettings.mRenamedPackages.get(names[i]);
1130 out[i] = cur != null ? cur : names[i];
1131 }
1132 }
1133 return out;
1134 }
1135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 public int getPackageUid(String packageName) {
1137 synchronized (mPackages) {
1138 PackageParser.Package p = mPackages.get(packageName);
1139 if(p != null) {
1140 return p.applicationInfo.uid;
1141 }
1142 PackageSetting ps = mSettings.mPackages.get(packageName);
1143 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1144 return -1;
1145 }
1146 p = ps.pkg;
1147 return p != null ? p.applicationInfo.uid : -1;
1148 }
1149 }
1150
1151 public int[] getPackageGids(String packageName) {
1152 synchronized (mPackages) {
1153 PackageParser.Package p = mPackages.get(packageName);
1154 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001155 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 + ": " + p);
1157 if (p != null) {
1158 final PackageSetting ps = (PackageSetting)p.mExtras;
1159 final SharedUserSetting suid = ps.sharedUser;
1160 return suid != null ? suid.gids : ps.gids;
1161 }
1162 }
1163 // stupid thing to indicate an error.
1164 return new int[0];
1165 }
1166
1167 public PermissionInfo getPermissionInfo(String name, int flags) {
1168 synchronized (mPackages) {
1169 final BasePermission p = mSettings.mPermissions.get(name);
1170 if (p != null && p.perm != null) {
1171 return PackageParser.generatePermissionInfo(p.perm, flags);
1172 }
1173 return null;
1174 }
1175 }
1176
1177 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1178 synchronized (mPackages) {
1179 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1180 for (BasePermission p : mSettings.mPermissions.values()) {
1181 if (group == null) {
1182 if (p.perm.info.group == null) {
1183 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1184 }
1185 } else {
1186 if (group.equals(p.perm.info.group)) {
1187 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1188 }
1189 }
1190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 if (out.size() > 0) {
1193 return out;
1194 }
1195 return mPermissionGroups.containsKey(group) ? out : null;
1196 }
1197 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1200 synchronized (mPackages) {
1201 return PackageParser.generatePermissionGroupInfo(
1202 mPermissionGroups.get(name), flags);
1203 }
1204 }
1205
1206 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1207 synchronized (mPackages) {
1208 final int N = mPermissionGroups.size();
1209 ArrayList<PermissionGroupInfo> out
1210 = new ArrayList<PermissionGroupInfo>(N);
1211 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1212 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1213 }
1214 return out;
1215 }
1216 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1219 PackageSetting ps = mSettings.mPackages.get(packageName);
1220 if(ps != null) {
1221 if(ps.pkg == null) {
1222 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1223 if(pInfo != null) {
1224 return pInfo.applicationInfo;
1225 }
1226 return null;
1227 }
1228 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1229 }
1230 return null;
1231 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1234 PackageSetting ps = mSettings.mPackages.get(packageName);
1235 if(ps != null) {
1236 if(ps.pkg == null) {
1237 ps.pkg = new PackageParser.Package(packageName);
1238 ps.pkg.applicationInfo.packageName = packageName;
1239 }
1240 return generatePackageInfo(ps.pkg, flags);
1241 }
1242 return null;
1243 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1246 synchronized (mPackages) {
1247 PackageParser.Package p = mPackages.get(packageName);
1248 if (Config.LOGV) Log.v(
1249 TAG, "getApplicationInfo " + packageName
1250 + ": " + p);
1251 if (p != null) {
1252 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001253 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 }
1255 if ("android".equals(packageName)||"system".equals(packageName)) {
1256 return mAndroidApplication;
1257 }
1258 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1259 return generateApplicationInfoFromSettingsLP(packageName, flags);
1260 }
1261 }
1262 return null;
1263 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001264
1265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1267 mContext.enforceCallingOrSelfPermission(
1268 android.Manifest.permission.CLEAR_APP_CACHE, null);
1269 // Queue up an async operation since clearing cache may take a little while.
1270 mHandler.post(new Runnable() {
1271 public void run() {
1272 mHandler.removeCallbacks(this);
1273 int retCode = -1;
1274 if (mInstaller != null) {
1275 retCode = mInstaller.freeCache(freeStorageSize);
1276 if (retCode < 0) {
1277 Log.w(TAG, "Couldn't clear application caches");
1278 }
1279 } //end if mInstaller
1280 if (observer != null) {
1281 try {
1282 observer.onRemoveCompleted(null, (retCode >= 0));
1283 } catch (RemoteException e) {
1284 Log.w(TAG, "RemoveException when invoking call back");
1285 }
1286 }
1287 }
1288 });
1289 }
1290
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001291 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001292 mContext.enforceCallingOrSelfPermission(
1293 android.Manifest.permission.CLEAR_APP_CACHE, null);
1294 // Queue up an async operation since clearing cache may take a little while.
1295 mHandler.post(new Runnable() {
1296 public void run() {
1297 mHandler.removeCallbacks(this);
1298 int retCode = -1;
1299 if (mInstaller != null) {
1300 retCode = mInstaller.freeCache(freeStorageSize);
1301 if (retCode < 0) {
1302 Log.w(TAG, "Couldn't clear application caches");
1303 }
1304 }
1305 if(pi != null) {
1306 try {
1307 // Callback via pending intent
1308 int code = (retCode >= 0) ? 1 : 0;
1309 pi.sendIntent(null, code, null,
1310 null, null);
1311 } catch (SendIntentException e1) {
1312 Log.i(TAG, "Failed to send pending intent");
1313 }
1314 }
1315 }
1316 });
1317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1320 synchronized (mPackages) {
1321 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001322
1323 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001325 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 }
1327 if (mResolveComponentName.equals(component)) {
1328 return mResolveActivity;
1329 }
1330 }
1331 return null;
1332 }
1333
1334 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1335 synchronized (mPackages) {
1336 PackageParser.Activity a = mReceivers.mActivities.get(component);
1337 if (Config.LOGV) Log.v(
1338 TAG, "getReceiverInfo " + component + ": " + a);
1339 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1340 return PackageParser.generateActivityInfo(a, flags);
1341 }
1342 }
1343 return null;
1344 }
1345
1346 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1347 synchronized (mPackages) {
1348 PackageParser.Service s = mServices.mServices.get(component);
1349 if (Config.LOGV) Log.v(
1350 TAG, "getServiceInfo " + component + ": " + s);
1351 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1352 return PackageParser.generateServiceInfo(s, flags);
1353 }
1354 }
1355 return null;
1356 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 public String[] getSystemSharedLibraryNames() {
1359 Set<String> libSet;
1360 synchronized (mPackages) {
1361 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001362 int size = libSet.size();
1363 if (size > 0) {
1364 String[] libs = new String[size];
1365 libSet.toArray(libs);
1366 return libs;
1367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001369 return null;
1370 }
1371
1372 public FeatureInfo[] getSystemAvailableFeatures() {
1373 Collection<FeatureInfo> featSet;
1374 synchronized (mPackages) {
1375 featSet = mAvailableFeatures.values();
1376 int size = featSet.size();
1377 if (size > 0) {
1378 FeatureInfo[] features = new FeatureInfo[size+1];
1379 featSet.toArray(features);
1380 FeatureInfo fi = new FeatureInfo();
1381 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1382 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1383 features[size] = fi;
1384 return features;
1385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387 return null;
1388 }
1389
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001390 public boolean hasSystemFeature(String name) {
1391 synchronized (mPackages) {
1392 return mAvailableFeatures.containsKey(name);
1393 }
1394 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 public int checkPermission(String permName, String pkgName) {
1397 synchronized (mPackages) {
1398 PackageParser.Package p = mPackages.get(pkgName);
1399 if (p != null && p.mExtras != null) {
1400 PackageSetting ps = (PackageSetting)p.mExtras;
1401 if (ps.sharedUser != null) {
1402 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1403 return PackageManager.PERMISSION_GRANTED;
1404 }
1405 } else if (ps.grantedPermissions.contains(permName)) {
1406 return PackageManager.PERMISSION_GRANTED;
1407 }
1408 }
1409 }
1410 return PackageManager.PERMISSION_DENIED;
1411 }
1412
1413 public int checkUidPermission(String permName, int uid) {
1414 synchronized (mPackages) {
1415 Object obj = mSettings.getUserIdLP(uid);
1416 if (obj != null) {
1417 if (obj instanceof SharedUserSetting) {
1418 SharedUserSetting sus = (SharedUserSetting)obj;
1419 if (sus.grantedPermissions.contains(permName)) {
1420 return PackageManager.PERMISSION_GRANTED;
1421 }
1422 } else if (obj instanceof PackageSetting) {
1423 PackageSetting ps = (PackageSetting)obj;
1424 if (ps.grantedPermissions.contains(permName)) {
1425 return PackageManager.PERMISSION_GRANTED;
1426 }
1427 }
1428 } else {
1429 HashSet<String> perms = mSystemPermissions.get(uid);
1430 if (perms != null && perms.contains(permName)) {
1431 return PackageManager.PERMISSION_GRANTED;
1432 }
1433 }
1434 }
1435 return PackageManager.PERMISSION_DENIED;
1436 }
1437
1438 private BasePermission findPermissionTreeLP(String permName) {
1439 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1440 if (permName.startsWith(bp.name) &&
1441 permName.length() > bp.name.length() &&
1442 permName.charAt(bp.name.length()) == '.') {
1443 return bp;
1444 }
1445 }
1446 return null;
1447 }
1448
1449 private BasePermission checkPermissionTreeLP(String permName) {
1450 if (permName != null) {
1451 BasePermission bp = findPermissionTreeLP(permName);
1452 if (bp != null) {
1453 if (bp.uid == Binder.getCallingUid()) {
1454 return bp;
1455 }
1456 throw new SecurityException("Calling uid "
1457 + Binder.getCallingUid()
1458 + " is not allowed to add to permission tree "
1459 + bp.name + " owned by uid " + bp.uid);
1460 }
1461 }
1462 throw new SecurityException("No permission tree found for " + permName);
1463 }
1464
1465 public boolean addPermission(PermissionInfo info) {
1466 synchronized (mPackages) {
1467 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1468 throw new SecurityException("Label must be specified in permission");
1469 }
1470 BasePermission tree = checkPermissionTreeLP(info.name);
1471 BasePermission bp = mSettings.mPermissions.get(info.name);
1472 boolean added = bp == null;
1473 if (added) {
1474 bp = new BasePermission(info.name, tree.sourcePackage,
1475 BasePermission.TYPE_DYNAMIC);
1476 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1477 throw new SecurityException(
1478 "Not allowed to modify non-dynamic permission "
1479 + info.name);
1480 }
1481 bp.perm = new PackageParser.Permission(tree.perm.owner,
1482 new PermissionInfo(info));
1483 bp.perm.info.packageName = tree.perm.info.packageName;
1484 bp.uid = tree.uid;
1485 if (added) {
1486 mSettings.mPermissions.put(info.name, bp);
1487 }
1488 mSettings.writeLP();
1489 return added;
1490 }
1491 }
1492
1493 public void removePermission(String name) {
1494 synchronized (mPackages) {
1495 checkPermissionTreeLP(name);
1496 BasePermission bp = mSettings.mPermissions.get(name);
1497 if (bp != null) {
1498 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1499 throw new SecurityException(
1500 "Not allowed to modify non-dynamic permission "
1501 + name);
1502 }
1503 mSettings.mPermissions.remove(name);
1504 mSettings.writeLP();
1505 }
1506 }
1507 }
1508
Dianne Hackborn854060af2009-07-09 18:14:31 -07001509 public boolean isProtectedBroadcast(String actionName) {
1510 synchronized (mPackages) {
1511 return mProtectedBroadcasts.contains(actionName);
1512 }
1513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 public int checkSignatures(String pkg1, String pkg2) {
1516 synchronized (mPackages) {
1517 PackageParser.Package p1 = mPackages.get(pkg1);
1518 PackageParser.Package p2 = mPackages.get(pkg2);
1519 if (p1 == null || p1.mExtras == null
1520 || p2 == null || p2.mExtras == null) {
1521 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1522 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001523 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 }
1525 }
1526
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001527 public int checkUidSignatures(int uid1, int uid2) {
1528 synchronized (mPackages) {
1529 Signature[] s1;
1530 Signature[] s2;
1531 Object obj = mSettings.getUserIdLP(uid1);
1532 if (obj != null) {
1533 if (obj instanceof SharedUserSetting) {
1534 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1535 } else if (obj instanceof PackageSetting) {
1536 s1 = ((PackageSetting)obj).signatures.mSignatures;
1537 } else {
1538 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1539 }
1540 } else {
1541 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1542 }
1543 obj = mSettings.getUserIdLP(uid2);
1544 if (obj != null) {
1545 if (obj instanceof SharedUserSetting) {
1546 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1547 } else if (obj instanceof PackageSetting) {
1548 s2 = ((PackageSetting)obj).signatures.mSignatures;
1549 } else {
1550 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1551 }
1552 } else {
1553 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1554 }
1555 return checkSignaturesLP(s1, s2);
1556 }
1557 }
1558
1559 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1560 if (s1 == null) {
1561 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1563 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1564 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001565 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1567 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001568 final int N1 = s1.length;
1569 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 for (int i=0; i<N1; i++) {
1571 boolean match = false;
1572 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001573 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 match = true;
1575 break;
1576 }
1577 }
1578 if (!match) {
1579 return PackageManager.SIGNATURE_NO_MATCH;
1580 }
1581 }
1582 return PackageManager.SIGNATURE_MATCH;
1583 }
1584
1585 public String[] getPackagesForUid(int uid) {
1586 synchronized (mPackages) {
1587 Object obj = mSettings.getUserIdLP(uid);
1588 if (obj instanceof SharedUserSetting) {
1589 SharedUserSetting sus = (SharedUserSetting)obj;
1590 final int N = sus.packages.size();
1591 String[] res = new String[N];
1592 Iterator<PackageSetting> it = sus.packages.iterator();
1593 int i=0;
1594 while (it.hasNext()) {
1595 res[i++] = it.next().name;
1596 }
1597 return res;
1598 } else if (obj instanceof PackageSetting) {
1599 PackageSetting ps = (PackageSetting)obj;
1600 return new String[] { ps.name };
1601 }
1602 }
1603 return null;
1604 }
1605
1606 public String getNameForUid(int uid) {
1607 synchronized (mPackages) {
1608 Object obj = mSettings.getUserIdLP(uid);
1609 if (obj instanceof SharedUserSetting) {
1610 SharedUserSetting sus = (SharedUserSetting)obj;
1611 return sus.name + ":" + sus.userId;
1612 } else if (obj instanceof PackageSetting) {
1613 PackageSetting ps = (PackageSetting)obj;
1614 return ps.name;
1615 }
1616 }
1617 return null;
1618 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 public int getUidForSharedUser(String sharedUserName) {
1621 if(sharedUserName == null) {
1622 return -1;
1623 }
1624 synchronized (mPackages) {
1625 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1626 if(suid == null) {
1627 return -1;
1628 }
1629 return suid.userId;
1630 }
1631 }
1632
1633 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1634 int flags) {
1635 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001636 return chooseBestActivity(intent, resolvedType, flags, query);
1637 }
1638
Mihai Predaeae850c2009-05-13 10:13:48 +02001639 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1640 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 if (query != null) {
1642 final int N = query.size();
1643 if (N == 1) {
1644 return query.get(0);
1645 } else if (N > 1) {
1646 // If there is more than one activity with the same priority,
1647 // then let the user decide between them.
1648 ResolveInfo r0 = query.get(0);
1649 ResolveInfo r1 = query.get(1);
1650 if (false) {
1651 System.out.println(r0.activityInfo.name +
1652 "=" + r0.priority + " vs " +
1653 r1.activityInfo.name +
1654 "=" + r1.priority);
1655 }
1656 // If the first activity has a higher priority, or a different
1657 // default, then it is always desireable to pick it.
1658 if (r0.priority != r1.priority
1659 || r0.preferredOrder != r1.preferredOrder
1660 || r0.isDefault != r1.isDefault) {
1661 return query.get(0);
1662 }
1663 // If we have saved a preference for a preferred activity for
1664 // this Intent, use that.
1665 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1666 flags, query, r0.priority);
1667 if (ri != null) {
1668 return ri;
1669 }
1670 return mResolveInfo;
1671 }
1672 }
1673 return null;
1674 }
1675
1676 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1677 int flags, List<ResolveInfo> query, int priority) {
1678 synchronized (mPackages) {
1679 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1680 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001681 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1683 if (prefs != null && prefs.size() > 0) {
1684 // First figure out how good the original match set is.
1685 // We will only allow preferred activities that came
1686 // from the same match quality.
1687 int match = 0;
1688 final int N = query.size();
1689 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1690 for (int j=0; j<N; j++) {
1691 ResolveInfo ri = query.get(j);
1692 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1693 + ": 0x" + Integer.toHexString(match));
1694 if (ri.match > match) match = ri.match;
1695 }
1696 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1697 + Integer.toHexString(match));
1698 match &= IntentFilter.MATCH_CATEGORY_MASK;
1699 final int M = prefs.size();
1700 for (int i=0; i<M; i++) {
1701 PreferredActivity pa = prefs.get(i);
1702 if (pa.mMatch != match) {
1703 continue;
1704 }
1705 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1706 if (DEBUG_PREFERRED) {
1707 Log.v(TAG, "Got preferred activity:");
1708 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1709 }
1710 if (ai != null) {
1711 for (int j=0; j<N; j++) {
1712 ResolveInfo ri = query.get(j);
1713 if (!ri.activityInfo.applicationInfo.packageName
1714 .equals(ai.applicationInfo.packageName)) {
1715 continue;
1716 }
1717 if (!ri.activityInfo.name.equals(ai.name)) {
1718 continue;
1719 }
1720
1721 // Okay we found a previously set preferred app.
1722 // If the result set is different from when this
1723 // was created, we need to clear it and re-ask the
1724 // user their preference.
1725 if (!pa.sameSet(query, priority)) {
1726 Log.i(TAG, "Result set changed, dropping preferred activity for "
1727 + intent + " type " + resolvedType);
1728 mSettings.mPreferredActivities.removeFilter(pa);
1729 return null;
1730 }
1731
1732 // Yay!
1733 return ri;
1734 }
1735 }
1736 }
1737 }
1738 }
1739 return null;
1740 }
1741
1742 public List<ResolveInfo> queryIntentActivities(Intent intent,
1743 String resolvedType, int flags) {
1744 ComponentName comp = intent.getComponent();
1745 if (comp != null) {
1746 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1747 ActivityInfo ai = getActivityInfo(comp, flags);
1748 if (ai != null) {
1749 ResolveInfo ri = new ResolveInfo();
1750 ri.activityInfo = ai;
1751 list.add(ri);
1752 }
1753 return list;
1754 }
1755
1756 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001757 String pkgName = intent.getPackage();
1758 if (pkgName == null) {
1759 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1760 resolvedType, flags);
1761 }
1762 PackageParser.Package pkg = mPackages.get(pkgName);
1763 if (pkg != null) {
1764 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1765 resolvedType, flags, pkg.activities);
1766 }
1767 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 }
1769 }
1770
1771 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1772 Intent[] specifics, String[] specificTypes, Intent intent,
1773 String resolvedType, int flags) {
1774 final String resultsAction = intent.getAction();
1775
1776 List<ResolveInfo> results = queryIntentActivities(
1777 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1778 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1779
1780 int specificsPos = 0;
1781 int N;
1782
1783 // todo: note that the algorithm used here is O(N^2). This
1784 // isn't a problem in our current environment, but if we start running
1785 // into situations where we have more than 5 or 10 matches then this
1786 // should probably be changed to something smarter...
1787
1788 // First we go through and resolve each of the specific items
1789 // that were supplied, taking care of removing any corresponding
1790 // duplicate items in the generic resolve list.
1791 if (specifics != null) {
1792 for (int i=0; i<specifics.length; i++) {
1793 final Intent sintent = specifics[i];
1794 if (sintent == null) {
1795 continue;
1796 }
1797
1798 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1799 String action = sintent.getAction();
1800 if (resultsAction != null && resultsAction.equals(action)) {
1801 // If this action was explicitly requested, then don't
1802 // remove things that have it.
1803 action = null;
1804 }
1805 ComponentName comp = sintent.getComponent();
1806 ResolveInfo ri = null;
1807 ActivityInfo ai = null;
1808 if (comp == null) {
1809 ri = resolveIntent(
1810 sintent,
1811 specificTypes != null ? specificTypes[i] : null,
1812 flags);
1813 if (ri == null) {
1814 continue;
1815 }
1816 if (ri == mResolveInfo) {
1817 // ACK! Must do something better with this.
1818 }
1819 ai = ri.activityInfo;
1820 comp = new ComponentName(ai.applicationInfo.packageName,
1821 ai.name);
1822 } else {
1823 ai = getActivityInfo(comp, flags);
1824 if (ai == null) {
1825 continue;
1826 }
1827 }
1828
1829 // Look for any generic query activities that are duplicates
1830 // of this specific one, and remove them from the results.
1831 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1832 N = results.size();
1833 int j;
1834 for (j=specificsPos; j<N; j++) {
1835 ResolveInfo sri = results.get(j);
1836 if ((sri.activityInfo.name.equals(comp.getClassName())
1837 && sri.activityInfo.applicationInfo.packageName.equals(
1838 comp.getPackageName()))
1839 || (action != null && sri.filter.matchAction(action))) {
1840 results.remove(j);
1841 if (Config.LOGV) Log.v(
1842 TAG, "Removing duplicate item from " + j
1843 + " due to specific " + specificsPos);
1844 if (ri == null) {
1845 ri = sri;
1846 }
1847 j--;
1848 N--;
1849 }
1850 }
1851
1852 // Add this specific item to its proper place.
1853 if (ri == null) {
1854 ri = new ResolveInfo();
1855 ri.activityInfo = ai;
1856 }
1857 results.add(specificsPos, ri);
1858 ri.specificIndex = i;
1859 specificsPos++;
1860 }
1861 }
1862
1863 // Now we go through the remaining generic results and remove any
1864 // duplicate actions that are found here.
1865 N = results.size();
1866 for (int i=specificsPos; i<N-1; i++) {
1867 final ResolveInfo rii = results.get(i);
1868 if (rii.filter == null) {
1869 continue;
1870 }
1871
1872 // Iterate over all of the actions of this result's intent
1873 // filter... typically this should be just one.
1874 final Iterator<String> it = rii.filter.actionsIterator();
1875 if (it == null) {
1876 continue;
1877 }
1878 while (it.hasNext()) {
1879 final String action = it.next();
1880 if (resultsAction != null && resultsAction.equals(action)) {
1881 // If this action was explicitly requested, then don't
1882 // remove things that have it.
1883 continue;
1884 }
1885 for (int j=i+1; j<N; j++) {
1886 final ResolveInfo rij = results.get(j);
1887 if (rij.filter != null && rij.filter.hasAction(action)) {
1888 results.remove(j);
1889 if (Config.LOGV) Log.v(
1890 TAG, "Removing duplicate item from " + j
1891 + " due to action " + action + " at " + i);
1892 j--;
1893 N--;
1894 }
1895 }
1896 }
1897
1898 // If the caller didn't request filter information, drop it now
1899 // so we don't have to marshall/unmarshall it.
1900 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1901 rii.filter = null;
1902 }
1903 }
1904
1905 // Filter out the caller activity if so requested.
1906 if (caller != null) {
1907 N = results.size();
1908 for (int i=0; i<N; i++) {
1909 ActivityInfo ainfo = results.get(i).activityInfo;
1910 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1911 && caller.getClassName().equals(ainfo.name)) {
1912 results.remove(i);
1913 break;
1914 }
1915 }
1916 }
1917
1918 // If the caller didn't request filter information,
1919 // drop them now so we don't have to
1920 // marshall/unmarshall it.
1921 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1922 N = results.size();
1923 for (int i=0; i<N; i++) {
1924 results.get(i).filter = null;
1925 }
1926 }
1927
1928 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1929 return results;
1930 }
1931
1932 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1933 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001934 ComponentName comp = intent.getComponent();
1935 if (comp != null) {
1936 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1937 ActivityInfo ai = getReceiverInfo(comp, flags);
1938 if (ai != null) {
1939 ResolveInfo ri = new ResolveInfo();
1940 ri.activityInfo = ai;
1941 list.add(ri);
1942 }
1943 return list;
1944 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001947 String pkgName = intent.getPackage();
1948 if (pkgName == null) {
1949 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1950 resolvedType, flags);
1951 }
1952 PackageParser.Package pkg = mPackages.get(pkgName);
1953 if (pkg != null) {
1954 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1955 resolvedType, flags, pkg.receivers);
1956 }
1957 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 }
1959 }
1960
1961 public ResolveInfo resolveService(Intent intent, String resolvedType,
1962 int flags) {
1963 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1964 flags);
1965 if (query != null) {
1966 if (query.size() >= 1) {
1967 // If there is more than one service with the same priority,
1968 // just arbitrarily pick the first one.
1969 return query.get(0);
1970 }
1971 }
1972 return null;
1973 }
1974
1975 public List<ResolveInfo> queryIntentServices(Intent intent,
1976 String resolvedType, int flags) {
1977 ComponentName comp = intent.getComponent();
1978 if (comp != null) {
1979 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1980 ServiceInfo si = getServiceInfo(comp, flags);
1981 if (si != null) {
1982 ResolveInfo ri = new ResolveInfo();
1983 ri.serviceInfo = si;
1984 list.add(ri);
1985 }
1986 return list;
1987 }
1988
1989 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001990 String pkgName = intent.getPackage();
1991 if (pkgName == null) {
1992 return (List<ResolveInfo>)mServices.queryIntent(intent,
1993 resolvedType, flags);
1994 }
1995 PackageParser.Package pkg = mPackages.get(pkgName);
1996 if (pkg != null) {
1997 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1998 resolvedType, flags, pkg.services);
1999 }
2000 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 }
2002 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 public List<PackageInfo> getInstalledPackages(int flags) {
2005 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2006
2007 synchronized (mPackages) {
2008 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2009 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2010 while (i.hasNext()) {
2011 final PackageSetting ps = i.next();
2012 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2013 if(psPkg != null) {
2014 finalList.add(psPkg);
2015 }
2016 }
2017 }
2018 else {
2019 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2020 while (i.hasNext()) {
2021 final PackageParser.Package p = i.next();
2022 if (p.applicationInfo != null) {
2023 PackageInfo pi = generatePackageInfo(p, flags);
2024 if(pi != null) {
2025 finalList.add(pi);
2026 }
2027 }
2028 }
2029 }
2030 }
2031 return finalList;
2032 }
2033
2034 public List<ApplicationInfo> getInstalledApplications(int flags) {
2035 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2036 synchronized(mPackages) {
2037 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2038 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2039 while (i.hasNext()) {
2040 final PackageSetting ps = i.next();
2041 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2042 if(ai != null) {
2043 finalList.add(ai);
2044 }
2045 }
2046 }
2047 else {
2048 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2049 while (i.hasNext()) {
2050 final PackageParser.Package p = i.next();
2051 if (p.applicationInfo != null) {
2052 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2053 if(ai != null) {
2054 finalList.add(ai);
2055 }
2056 }
2057 }
2058 }
2059 }
2060 return finalList;
2061 }
2062
2063 public List<ApplicationInfo> getPersistentApplications(int flags) {
2064 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2065
2066 synchronized (mPackages) {
2067 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2068 while (i.hasNext()) {
2069 PackageParser.Package p = i.next();
2070 if (p.applicationInfo != null
2071 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
2072 && (!mSafeMode || (p.applicationInfo.flags
2073 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2074 finalList.add(p.applicationInfo);
2075 }
2076 }
2077 }
2078
2079 return finalList;
2080 }
2081
2082 public ProviderInfo resolveContentProvider(String name, int flags) {
2083 synchronized (mPackages) {
2084 final PackageParser.Provider provider = mProviders.get(name);
2085 return provider != null
2086 && mSettings.isEnabledLP(provider.info, flags)
2087 && (!mSafeMode || (provider.info.applicationInfo.flags
2088 &ApplicationInfo.FLAG_SYSTEM) != 0)
2089 ? PackageParser.generateProviderInfo(provider, flags)
2090 : null;
2091 }
2092 }
2093
Fred Quintana718d8a22009-04-29 17:53:20 -07002094 /**
2095 * @deprecated
2096 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 public void querySyncProviders(List outNames, List outInfo) {
2098 synchronized (mPackages) {
2099 Iterator<Map.Entry<String, PackageParser.Provider>> i
2100 = mProviders.entrySet().iterator();
2101
2102 while (i.hasNext()) {
2103 Map.Entry<String, PackageParser.Provider> entry = i.next();
2104 PackageParser.Provider p = entry.getValue();
2105
2106 if (p.syncable
2107 && (!mSafeMode || (p.info.applicationInfo.flags
2108 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2109 outNames.add(entry.getKey());
2110 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2111 }
2112 }
2113 }
2114 }
2115
2116 public List<ProviderInfo> queryContentProviders(String processName,
2117 int uid, int flags) {
2118 ArrayList<ProviderInfo> finalList = null;
2119
2120 synchronized (mPackages) {
2121 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2122 while (i.hasNext()) {
2123 PackageParser.Provider p = i.next();
2124 if (p.info.authority != null
2125 && (processName == null ||
2126 (p.info.processName.equals(processName)
2127 && p.info.applicationInfo.uid == uid))
2128 && mSettings.isEnabledLP(p.info, flags)
2129 && (!mSafeMode || (p.info.applicationInfo.flags
2130 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2131 if (finalList == null) {
2132 finalList = new ArrayList<ProviderInfo>(3);
2133 }
2134 finalList.add(PackageParser.generateProviderInfo(p,
2135 flags));
2136 }
2137 }
2138 }
2139
2140 if (finalList != null) {
2141 Collections.sort(finalList, mProviderInitOrderSorter);
2142 }
2143
2144 return finalList;
2145 }
2146
2147 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2148 int flags) {
2149 synchronized (mPackages) {
2150 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2151 return PackageParser.generateInstrumentationInfo(i, flags);
2152 }
2153 }
2154
2155 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2156 int flags) {
2157 ArrayList<InstrumentationInfo> finalList =
2158 new ArrayList<InstrumentationInfo>();
2159
2160 synchronized (mPackages) {
2161 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2162 while (i.hasNext()) {
2163 PackageParser.Instrumentation p = i.next();
2164 if (targetPackage == null
2165 || targetPackage.equals(p.info.targetPackage)) {
2166 finalList.add(PackageParser.generateInstrumentationInfo(p,
2167 flags));
2168 }
2169 }
2170 }
2171
2172 return finalList;
2173 }
2174
2175 private void scanDirLI(File dir, int flags, int scanMode) {
2176 Log.d(TAG, "Scanning app dir " + dir);
2177
2178 String[] files = dir.list();
2179
2180 int i;
2181 for (i=0; i<files.length; i++) {
2182 File file = new File(dir, files[i]);
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002183 if (files[i] != null && files[i].endsWith(".zip")) {
2184 // Public resource for forward locked package. Ignore
2185 continue;
2186 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002187 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002189 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002190 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2191 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002192 // Delete the apk
2193 Log.w(TAG, "Cleaning up failed install of " + file);
2194 file.delete();
2195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 }
2197 }
2198
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002199 private static File getSettingsProblemFile() {
2200 File dataDir = Environment.getDataDirectory();
2201 File systemDir = new File(dataDir, "system");
2202 File fname = new File(systemDir, "uiderrors.txt");
2203 return fname;
2204 }
2205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 private static void reportSettingsProblem(int priority, String msg) {
2207 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002208 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 FileOutputStream out = new FileOutputStream(fname, true);
2210 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002211 SimpleDateFormat formatter = new SimpleDateFormat();
2212 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2213 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 pw.close();
2215 FileUtils.setPermissions(
2216 fname.toString(),
2217 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2218 -1, -1);
2219 } catch (java.io.IOException e) {
2220 }
2221 Log.println(priority, TAG, msg);
2222 }
2223
2224 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2225 PackageParser.Package pkg, File srcFile, int parseFlags) {
2226 if (GET_CERTIFICATES) {
2227 if (ps == null || !ps.codePath.equals(srcFile)
2228 || ps.getTimeStamp() != srcFile.lastModified()) {
2229 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2230 if (!pp.collectCertificates(pkg, parseFlags)) {
2231 mLastScanError = pp.getParseError();
2232 return false;
2233 }
2234 }
2235 }
2236 return true;
2237 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 /*
2240 * Scan a package and return the newly parsed package.
2241 * Returns null in case of errors and the error code is stored in mLastScanError
2242 */
2243 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002244 int parseFlags, int scanMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002246 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002248 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002251 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 if (pkg == null) {
2253 mLastScanError = pp.getParseError();
2254 return null;
2255 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002256 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 PackageSetting updatedPkg;
2258 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002259 // Look to see if we already know about this package.
2260 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
2261 if (oldName != null && oldName.equals(pkg.mOriginalPackage)) {
2262 // This package has been renamed to its original name. Let's
2263 // use that.
2264 ps = mSettings.peekPackageLP(pkg.mOriginalPackage);
2265 }
2266 // If there was no original package, see one for the real package name.
2267 if (ps == null) {
2268 ps = mSettings.peekPackageLP(pkg.packageName);
2269 }
2270 // Check to see if this package could be hiding/updating a system
2271 // package. Must look for it either under the original or real
2272 // package name depending on our state.
2273 updatedPkg = mSettings.mDisabledSysPackages.get(
2274 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002276 // First check if this is a system package that may involve an update
2277 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2278 if (!ps.codePath.equals(scanFile)) {
2279 // The path has changed from what was last scanned... check the
2280 // version of the new path against what we have stored to determine
2281 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002282 if (pkg.mVersionCode < ps.versionCode) {
2283 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002284 // Ignore entry. Skip it.
2285 Log.i(TAG, "Package " + ps.name + " at " + scanFile
2286 + "ignored: updated version " + ps.versionCode
2287 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002288 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2289 return null;
2290 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002291 // The current app on the system partion is better than
2292 // what we have updated to on the data partition; switch
2293 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002294 // At this point, its safely assumed that package installation for
2295 // apps in system partition will go through. If not there won't be a working
2296 // version of the app
2297 synchronized (mPackages) {
2298 // Just remove the loaded entries from package lists.
2299 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002300 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002301 Log.w(TAG, "Package " + ps.name + " at " + scanFile
2302 + "reverting from " + ps.codePathString
2303 + ": new version " + pkg.mVersionCode
2304 + " better than installed " + ps.versionCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002305 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2306 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002307 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002311 if (updatedPkg != null) {
2312 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2313 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2314 }
2315 // Verify certificates against what was last scanned
2316 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2317 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2318 return null;
2319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 // The apk is forward locked (not public) if its code and resources
2321 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002322 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002324 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002325 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002326
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002327 String codePath = null;
2328 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002329 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2330 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002331 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002332 } else {
2333 // Should not happen at all. Just log an error.
2334 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2335 }
2336 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002337 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002338 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002339 codePath = pkg.mScanPath;
2340 // Set application objects path explicitly.
2341 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002343 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002344 }
2345
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002346 private static void setApplicationInfoPaths(PackageParser.Package pkg,
2347 String destCodePath, String destResPath) {
2348 pkg.mPath = pkg.mScanPath = destCodePath;
2349 pkg.applicationInfo.sourceDir = destCodePath;
2350 pkg.applicationInfo.publicSourceDir = destResPath;
2351 }
2352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 private static String fixProcessName(String defProcessName,
2354 String processName, int uid) {
2355 if (processName == null) {
2356 return defProcessName;
2357 }
2358 return processName;
2359 }
2360
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002361 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2363 if (pkg.mSignatures != null) {
2364 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2365 updateSignature)) {
2366 Log.e(TAG, "Package " + pkg.packageName
2367 + " signatures do not match the previously installed version; ignoring!");
2368 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2369 return false;
2370 }
2371
2372 if (pkgSetting.sharedUser != null) {
2373 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2374 pkg.mSignatures, updateSignature)) {
2375 Log.e(TAG, "Package " + pkg.packageName
2376 + " has no signatures that match those in shared user "
2377 + pkgSetting.sharedUser.name + "; ignoring!");
2378 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2379 return false;
2380 }
2381 }
2382 } else {
2383 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2384 }
2385 return true;
2386 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002387
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002388 public boolean performDexOpt(String packageName) {
2389 if (!mNoDexOpt) {
2390 return false;
2391 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002392
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002393 PackageParser.Package p;
2394 synchronized (mPackages) {
2395 p = mPackages.get(packageName);
2396 if (p == null || p.mDidDexOpt) {
2397 return false;
2398 }
2399 }
2400 synchronized (mInstallLock) {
2401 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2402 }
2403 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002404
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002405 static final int DEX_OPT_SKIPPED = 0;
2406 static final int DEX_OPT_PERFORMED = 1;
2407 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002408
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002409 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2410 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002411 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002412 String path = pkg.mScanPath;
2413 int ret = 0;
2414 try {
2415 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002416 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002417 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002418 pkg.mDidDexOpt = true;
2419 performed = true;
2420 }
2421 } catch (FileNotFoundException e) {
2422 Log.w(TAG, "Apk not found for dexopt: " + path);
2423 ret = -1;
2424 } catch (IOException e) {
2425 Log.w(TAG, "Exception reading apk: " + path, e);
2426 ret = -1;
2427 }
2428 if (ret < 0) {
2429 //error from installer
2430 return DEX_OPT_FAILED;
2431 }
2432 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002433
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002434 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2435 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002436
2437 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2438 return Environment.isEncryptedFilesystemEnabled() &&
2439 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2440 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002441
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002442 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2443 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2444 Log.w(TAG, "Unable to update from " + oldPkg.name
2445 + " to " + newPkg.packageName
2446 + ": old package not in system partition");
2447 return false;
2448 } else if (mPackages.get(oldPkg.name) != null) {
2449 Log.w(TAG, "Unable to update from " + oldPkg.name
2450 + " to " + newPkg.packageName
2451 + ": old package still exists");
2452 return false;
2453 }
2454 return true;
2455 }
2456
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002457 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
2458 int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002459 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002460 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2461 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002462 // Bail out. The resource and code paths haven't been set.
2463 Log.w(TAG, " Code and resource paths haven't been set correctly");
2464 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2465 return null;
2466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 mScanningPath = scanFile;
2468 if (pkg == null) {
2469 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2470 return null;
2471 }
2472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002473 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2474 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2475 }
2476
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002477 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 synchronized (mPackages) {
2479 if (mAndroidApplication != null) {
2480 Log.w(TAG, "*************************************************");
2481 Log.w(TAG, "Core android package being redefined. Skipping.");
2482 Log.w(TAG, " file=" + mScanningPath);
2483 Log.w(TAG, "*************************************************");
2484 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2485 return null;
2486 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 // Set up information for our fall-back user intent resolution
2489 // activity.
2490 mPlatformPackage = pkg;
2491 pkg.mVersionCode = mSdkVersion;
2492 mAndroidApplication = pkg.applicationInfo;
2493 mResolveActivity.applicationInfo = mAndroidApplication;
2494 mResolveActivity.name = ResolverActivity.class.getName();
2495 mResolveActivity.packageName = mAndroidApplication.packageName;
2496 mResolveActivity.processName = mAndroidApplication.processName;
2497 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2498 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2499 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2500 mResolveActivity.exported = true;
2501 mResolveActivity.enabled = true;
2502 mResolveInfo.activityInfo = mResolveActivity;
2503 mResolveInfo.priority = 0;
2504 mResolveInfo.preferredOrder = 0;
2505 mResolveInfo.match = 0;
2506 mResolveComponentName = new ComponentName(
2507 mAndroidApplication.packageName, mResolveActivity.name);
2508 }
2509 }
2510
2511 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002512 TAG, "Scanning package " + pkg.packageName);
2513 if (mPackages.containsKey(pkg.packageName)
2514 || mSharedLibraries.containsKey(pkg.packageName)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002515 Log.w(TAG, "*************************************************");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002516 Log.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 + " already installed. Skipping duplicate.");
2518 Log.w(TAG, "*************************************************");
2519 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2520 return null;
2521 }
2522
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002523 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002524 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2525 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 SharedUserSetting suid = null;
2528 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002531
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002532 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2533 // Only system apps can use these features.
2534 pkg.mOriginalPackage = null;
2535 pkg.mRealPackage = null;
2536 pkg.mAdoptPermissions = null;
2537 }
2538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 synchronized (mPackages) {
2540 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002541 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2542 if (mTmpSharedLibraries == null ||
2543 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2544 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2545 }
2546 int num = 0;
2547 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2548 for (int i=0; i<N; i++) {
2549 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002550 if (file == null) {
2551 Log.e(TAG, "Package " + pkg.packageName
2552 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002553 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2555 return null;
2556 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002557 mTmpSharedLibraries[num] = file;
2558 num++;
2559 }
2560 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2561 for (int i=0; i<N; i++) {
2562 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2563 if (file == null) {
2564 Log.w(TAG, "Package " + pkg.packageName
2565 + " desires unavailable shared library "
2566 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2567 } else {
2568 mTmpSharedLibraries[num] = file;
2569 num++;
2570 }
2571 }
2572 if (num > 0) {
2573 pkg.usesLibraryFiles = new String[num];
2574 System.arraycopy(mTmpSharedLibraries, 0,
2575 pkg.usesLibraryFiles, 0, num);
2576 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002577
Dianne Hackborn49237342009-08-27 20:08:01 -07002578 if (pkg.reqFeatures != null) {
2579 N = pkg.reqFeatures.size();
2580 for (int i=0; i<N; i++) {
2581 FeatureInfo fi = pkg.reqFeatures.get(i);
2582 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2583 // Don't care.
2584 continue;
2585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002586
Dianne Hackborn49237342009-08-27 20:08:01 -07002587 if (fi.name != null) {
2588 if (mAvailableFeatures.get(fi.name) == null) {
2589 Log.e(TAG, "Package " + pkg.packageName
2590 + " requires unavailable feature "
2591 + fi.name + "; failing!");
2592 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2593 return null;
2594 }
2595 }
2596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 }
2598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 if (pkg.mSharedUserId != null) {
2601 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2602 pkg.applicationInfo.flags, true);
2603 if (suid == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002604 Log.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 + " for shared user failed");
2606 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2607 return null;
2608 }
2609 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2610 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2611 + suid.userId + "): packages=" + suid.packages);
2612 }
2613 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002614
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002615 if (false) {
2616 if (pkg.mOriginalPackage != null) {
2617 Log.w(TAG, "WAITING FOR DEBUGGER");
2618 Debug.waitForDebugger();
2619 Log.i(TAG, "Package " + pkg.packageName + " from original package"
2620 + pkg.mOriginalPackage);
2621 }
2622 }
2623
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002624 // Check if we are renaming from an original package name.
2625 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002626 String realName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002627 if (pkg.mOriginalPackage != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002628 // This package may need to be renamed to a previously
2629 // installed name. Let's check on that...
2630 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
2631 if (pkg.mOriginalPackage.equals(renamed)) {
2632 // This package had originally been installed as the
2633 // original name, and we have already taken care of
2634 // transitioning to the new one. Just update the new
2635 // one to continue using the old name.
2636 realName = pkg.mRealPackage;
2637 if (!pkg.packageName.equals(renamed)) {
2638 // Callers into this function may have already taken
2639 // care of renaming the package; only do it here if
2640 // it is not already done.
2641 pkg.setPackageName(renamed);
2642 }
2643
2644 } else if ((origPackage
2645 = mSettings.peekPackageLP(pkg.mOriginalPackage)) != null) {
2646 // We do have the package already installed under its
2647 // original name... should we use it?
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002648 if (!verifyPackageUpdate(origPackage, pkg)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002649 // New package is not compatible with original.
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002650 origPackage = null;
2651 } else if (origPackage.sharedUser != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002652 // Make sure uid is compatible between packages.
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002653 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
2654 Log.w(TAG, "Unable to migrate data from " + origPackage.name
2655 + " to " + pkg.packageName + ": old uid "
2656 + origPackage.sharedUser.name
2657 + " differs from " + pkg.mSharedUserId);
2658 origPackage = null;
2659 }
2660 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002661 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
2662 + pkg.packageName + " to old name " + origPackage.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002663 }
2664 }
2665 }
2666
2667 if (mTransferedPackages.contains(pkg.packageName)) {
2668 Log.w(TAG, "Package " + pkg.packageName
2669 + " was transferred to another, but its .apk remains");
2670 }
2671
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002672 // Just create the setting, don't add it yet. For already existing packages
2673 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002674 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 destResourceFile, pkg.applicationInfo.flags, true, false);
2676 if (pkgSetting == null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002677 Log.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2679 return null;
2680 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002681
2682 if (pkgSetting.origPackage != null) {
2683 // If we are first transitioning from an original package,
2684 // fix up the new package's name now. We need to do this after
2685 // looking up the package under its new name, so getPackageLP
2686 // can take care of fiddling things correctly.
2687 pkg.setPackageName(origPackage.name);
2688
2689 // File a report about this.
2690 String msg = "New package " + pkgSetting.realName
2691 + " renamed to replace old package " + pkgSetting.name;
2692 reportSettingsProblem(Log.WARN, msg);
2693
2694 // Make a note of it.
2695 mTransferedPackages.add(origPackage.name);
2696
2697 // No longer need to retain this.
2698 pkgSetting.origPackage = null;
2699 }
2700
2701 if (realName != null) {
2702 // Make a note of it.
2703 mTransferedPackages.add(pkg.packageName);
2704 }
2705
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002706 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002707 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2708 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 pkg.applicationInfo.uid = pkgSetting.userId;
2711 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002712
2713 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002714 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2715 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2716 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2717 return null;
2718 }
2719 // The signature has changed, but this package is in the system
2720 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002721 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 // However... if this package is part of a shared user, but it
2723 // doesn't match the signature of the shared user, let's fail.
2724 // What this means is that you can't change the signatures
2725 // associated with an overall shared user, which doesn't seem all
2726 // that unreasonable.
2727 if (pkgSetting.sharedUser != null) {
2728 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2729 pkg.mSignatures, false)) {
2730 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2731 return null;
2732 }
2733 }
2734 removeExisting = true;
2735 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002736
The Android Open Source Project10592532009-03-18 17:39:46 -07002737 // Verify that this new package doesn't have any content providers
2738 // that conflict with existing packages. Only do this if the
2739 // package isn't already installed, since we don't want to break
2740 // things that are installed.
2741 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2742 int N = pkg.providers.size();
2743 int i;
2744 for (i=0; i<N; i++) {
2745 PackageParser.Provider p = pkg.providers.get(i);
2746 String names[] = p.info.authority.split(";");
2747 for (int j = 0; j < names.length; j++) {
2748 if (mProviders.containsKey(names[j])) {
2749 PackageParser.Provider other = mProviders.get(names[j]);
2750 Log.w(TAG, "Can't install because provider name " + names[j] +
2751 " (in package " + pkg.applicationInfo.packageName +
2752 ") is already used by "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002753 + ((other != null && other.getComponentName() != null)
2754 ? other.getComponentName().getPackageName() : "?"));
The Android Open Source Project10592532009-03-18 17:39:46 -07002755 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2756 return null;
2757 }
2758 }
2759 }
2760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 }
2762
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002763 final String pkgName = pkg.packageName;
2764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002766 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002768 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769 if (ret != 0) {
2770 String msg = "System package " + pkg.packageName
2771 + " could not have data directory erased after signature change.";
2772 reportSettingsProblem(Log.WARN, msg);
2773 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2774 return null;
2775 }
2776 }
2777 Log.w(TAG, "System package " + pkg.packageName
2778 + " signature changed: existing data removed.");
2779 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002781
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002782 if (pkg.mAdoptPermissions != null) {
2783 // This package wants to adopt ownership of permissions from
2784 // another package.
2785 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
2786 String origName = pkg.mAdoptPermissions.get(i);
2787 PackageSetting orig = mSettings.peekPackageLP(origName);
2788 if (orig != null) {
2789 if (verifyPackageUpdate(orig, pkg)) {
2790 Log.i(TAG, "Adopting permissions from "
2791 + origName + " to " + pkg.packageName);
2792 mSettings.transferPermissions(origName, pkg.packageName);
2793 }
2794 }
2795 }
2796 }
2797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798 long scanFileTime = scanFile.lastModified();
2799 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2800 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2801 pkg.applicationInfo.processName = fixProcessName(
2802 pkg.applicationInfo.packageName,
2803 pkg.applicationInfo.processName,
2804 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805
2806 File dataPath;
2807 if (mPlatformPackage == pkg) {
2808 // The system package is special.
2809 dataPath = new File (Environment.getDataDirectory(), "system");
2810 pkg.applicationInfo.dataDir = dataPath.getPath();
2811 } else {
2812 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002813 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2814 if (useEncryptedFSDir) {
2815 dataPath = new File(mSecureAppDataDir, pkgName);
2816 } else {
2817 dataPath = new File(mAppDataDir, pkgName);
2818 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002819
2820 boolean uidError = false;
2821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 if (dataPath.exists()) {
2823 mOutPermissions[1] = 0;
2824 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2825 if (mOutPermissions[1] == pkg.applicationInfo.uid
2826 || !Process.supportsProcesses()) {
2827 pkg.applicationInfo.dataDir = dataPath.getPath();
2828 } else {
2829 boolean recovered = false;
2830 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2831 // If this is a system app, we can at least delete its
2832 // current data so the application will still work.
2833 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002834 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002835 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836 // Old data gone!
2837 String msg = "System package " + pkg.packageName
2838 + " has changed from uid: "
2839 + mOutPermissions[1] + " to "
2840 + pkg.applicationInfo.uid + "; old data erased";
2841 reportSettingsProblem(Log.WARN, msg);
2842 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002845 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 pkg.applicationInfo.uid);
2847 if (ret == -1) {
2848 // Ack should not happen!
2849 msg = "System package " + pkg.packageName
2850 + " could not have data directory re-created after delete.";
2851 reportSettingsProblem(Log.WARN, msg);
2852 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2853 return null;
2854 }
2855 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857 if (!recovered) {
2858 mHasSystemUidErrors = true;
2859 }
2860 }
2861 if (!recovered) {
2862 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2863 + pkg.applicationInfo.uid + "/fs_"
2864 + mOutPermissions[1];
2865 String msg = "Package " + pkg.packageName
2866 + " has mismatched uid: "
2867 + mOutPermissions[1] + " on disk, "
2868 + pkg.applicationInfo.uid + " in settings";
2869 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002870 mSettings.mReadMessages.append(msg);
2871 mSettings.mReadMessages.append('\n');
2872 uidError = true;
2873 if (!pkgSetting.uidError) {
2874 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 }
2877 }
2878 }
2879 pkg.applicationInfo.dataDir = dataPath.getPath();
2880 } else {
2881 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2882 Log.v(TAG, "Want this data dir: " + dataPath);
2883 //invoke installer to do the actual installation
2884 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002885 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 pkg.applicationInfo.uid);
2887 if(ret < 0) {
2888 // Error from installer
2889 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2890 return null;
2891 }
2892 } else {
2893 dataPath.mkdirs();
2894 if (dataPath.exists()) {
2895 FileUtils.setPermissions(
2896 dataPath.toString(),
2897 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2898 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2899 }
2900 }
2901 if (dataPath.exists()) {
2902 pkg.applicationInfo.dataDir = dataPath.getPath();
2903 } else {
2904 Log.w(TAG, "Unable to create data directory: " + dataPath);
2905 pkg.applicationInfo.dataDir = null;
2906 }
2907 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002908
2909 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910 }
2911
2912 // Perform shared library installation and dex validation and
2913 // optimization, if this is not a system app.
2914 if (mInstaller != null) {
2915 String path = scanFile.getPath();
2916 if (scanFileNewer) {
2917 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002918 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2919 if (err != PackageManager.INSTALL_SUCCEEDED) {
2920 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 return null;
2922 }
2923 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002924 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002925
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002926 if ((scanMode&SCAN_NO_DEX) == 0) {
2927 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2929 return null;
2930 }
2931 }
2932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 if (mFactoryTest && pkg.requestedPermissions.contains(
2935 android.Manifest.permission.FACTORY_TEST)) {
2936 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2937 }
2938
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002939 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 if ((scanMode&SCAN_MONITOR) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 mAppDirs.put(pkg.mPath, pkg);
2942 }
2943
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002944 // Request the ActivityManager to kill the process(only for existing packages)
2945 // so that we do not end up in a confused state while the user is still using the older
2946 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002947 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002948 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002949 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002950 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002951
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002952 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002954 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002955 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002956 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08002957 // Make sure we don't accidentally delete its data.
2958 mSettings.mPackagesToBeCleaned.remove(pkgName);
2959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 int N = pkg.providers.size();
2961 StringBuilder r = null;
2962 int i;
2963 for (i=0; i<N; i++) {
2964 PackageParser.Provider p = pkg.providers.get(i);
2965 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2966 p.info.processName, pkg.applicationInfo.uid);
2967 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2968 p.info.name), p);
2969 p.syncable = p.info.isSyncable;
2970 String names[] = p.info.authority.split(";");
2971 p.info.authority = null;
2972 for (int j = 0; j < names.length; j++) {
2973 if (j == 1 && p.syncable) {
2974 // We only want the first authority for a provider to possibly be
2975 // syncable, so if we already added this provider using a different
2976 // authority clear the syncable flag. We copy the provider before
2977 // changing it because the mProviders object contains a reference
2978 // to a provider that we don't want to change.
2979 // Only do this for the second authority since the resulting provider
2980 // object can be the same for all future authorities for this provider.
2981 p = new PackageParser.Provider(p);
2982 p.syncable = false;
2983 }
2984 if (!mProviders.containsKey(names[j])) {
2985 mProviders.put(names[j], p);
2986 if (p.info.authority == null) {
2987 p.info.authority = names[j];
2988 } else {
2989 p.info.authority = p.info.authority + ";" + names[j];
2990 }
2991 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2992 Log.d(TAG, "Registered content provider: " + names[j] +
2993 ", className = " + p.info.name +
2994 ", isSyncable = " + p.info.isSyncable);
2995 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002996 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 Log.w(TAG, "Skipping provider name " + names[j] +
2998 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002999 "): name already used by "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003000 + ((other != null && other.getComponentName() != null)
3001 ? other.getComponentName().getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 }
3003 }
3004 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3005 if (r == null) {
3006 r = new StringBuilder(256);
3007 } else {
3008 r.append(' ');
3009 }
3010 r.append(p.info.name);
3011 }
3012 }
3013 if (r != null) {
3014 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3015 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 N = pkg.services.size();
3018 r = null;
3019 for (i=0; i<N; i++) {
3020 PackageParser.Service s = pkg.services.get(i);
3021 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3022 s.info.processName, pkg.applicationInfo.uid);
3023 mServices.addService(s);
3024 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3025 if (r == null) {
3026 r = new StringBuilder(256);
3027 } else {
3028 r.append(' ');
3029 }
3030 r.append(s.info.name);
3031 }
3032 }
3033 if (r != null) {
3034 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3035 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 N = pkg.receivers.size();
3038 r = null;
3039 for (i=0; i<N; i++) {
3040 PackageParser.Activity a = pkg.receivers.get(i);
3041 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3042 a.info.processName, pkg.applicationInfo.uid);
3043 mReceivers.addActivity(a, "receiver");
3044 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3045 if (r == null) {
3046 r = new StringBuilder(256);
3047 } else {
3048 r.append(' ');
3049 }
3050 r.append(a.info.name);
3051 }
3052 }
3053 if (r != null) {
3054 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3055 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003057 N = pkg.activities.size();
3058 r = null;
3059 for (i=0; i<N; i++) {
3060 PackageParser.Activity a = pkg.activities.get(i);
3061 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3062 a.info.processName, pkg.applicationInfo.uid);
3063 mActivities.addActivity(a, "activity");
3064 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3065 if (r == null) {
3066 r = new StringBuilder(256);
3067 } else {
3068 r.append(' ');
3069 }
3070 r.append(a.info.name);
3071 }
3072 }
3073 if (r != null) {
3074 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3075 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 N = pkg.permissionGroups.size();
3078 r = null;
3079 for (i=0; i<N; i++) {
3080 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3081 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3082 if (cur == null) {
3083 mPermissionGroups.put(pg.info.name, pg);
3084 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3085 if (r == null) {
3086 r = new StringBuilder(256);
3087 } else {
3088 r.append(' ');
3089 }
3090 r.append(pg.info.name);
3091 }
3092 } else {
3093 Log.w(TAG, "Permission group " + pg.info.name + " from package "
3094 + pg.info.packageName + " ignored: original from "
3095 + cur.info.packageName);
3096 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3097 if (r == null) {
3098 r = new StringBuilder(256);
3099 } else {
3100 r.append(' ');
3101 }
3102 r.append("DUP:");
3103 r.append(pg.info.name);
3104 }
3105 }
3106 }
3107 if (r != null) {
3108 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3109 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 N = pkg.permissions.size();
3112 r = null;
3113 for (i=0; i<N; i++) {
3114 PackageParser.Permission p = pkg.permissions.get(i);
3115 HashMap<String, BasePermission> permissionMap =
3116 p.tree ? mSettings.mPermissionTrees
3117 : mSettings.mPermissions;
3118 p.group = mPermissionGroups.get(p.info.group);
3119 if (p.info.group == null || p.group != null) {
3120 BasePermission bp = permissionMap.get(p.info.name);
3121 if (bp == null) {
3122 bp = new BasePermission(p.info.name, p.info.packageName,
3123 BasePermission.TYPE_NORMAL);
3124 permissionMap.put(p.info.name, bp);
3125 }
3126 if (bp.perm == null) {
3127 if (bp.sourcePackage == null
3128 || bp.sourcePackage.equals(p.info.packageName)) {
3129 BasePermission tree = findPermissionTreeLP(p.info.name);
3130 if (tree == null
3131 || tree.sourcePackage.equals(p.info.packageName)) {
3132 bp.perm = p;
3133 bp.uid = pkg.applicationInfo.uid;
3134 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3135 if (r == null) {
3136 r = new StringBuilder(256);
3137 } else {
3138 r.append(' ');
3139 }
3140 r.append(p.info.name);
3141 }
3142 } else {
3143 Log.w(TAG, "Permission " + p.info.name + " from package "
3144 + p.info.packageName + " ignored: base tree "
3145 + tree.name + " is from package "
3146 + tree.sourcePackage);
3147 }
3148 } else {
3149 Log.w(TAG, "Permission " + p.info.name + " from package "
3150 + p.info.packageName + " ignored: original from "
3151 + bp.sourcePackage);
3152 }
3153 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3154 if (r == null) {
3155 r = new StringBuilder(256);
3156 } else {
3157 r.append(' ');
3158 }
3159 r.append("DUP:");
3160 r.append(p.info.name);
3161 }
3162 } else {
3163 Log.w(TAG, "Permission " + p.info.name + " from package "
3164 + p.info.packageName + " ignored: no group "
3165 + p.group);
3166 }
3167 }
3168 if (r != null) {
3169 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3170 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 N = pkg.instrumentation.size();
3173 r = null;
3174 for (i=0; i<N; i++) {
3175 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3176 a.info.packageName = pkg.applicationInfo.packageName;
3177 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3178 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3179 a.info.dataDir = pkg.applicationInfo.dataDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003180 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3182 if (r == null) {
3183 r = new StringBuilder(256);
3184 } else {
3185 r.append(' ');
3186 }
3187 r.append(a.info.name);
3188 }
3189 }
3190 if (r != null) {
3191 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003193
Dianne Hackborn854060af2009-07-09 18:14:31 -07003194 if (pkg.protectedBroadcasts != null) {
3195 N = pkg.protectedBroadcasts.size();
3196 for (i=0; i<N; i++) {
3197 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3198 }
3199 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 pkgSetting.setTimeStamp(scanFileTime);
3202 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003204 return pkg;
3205 }
3206
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003207 private void killApplication(String pkgName, int uid) {
3208 // Request the ActivityManager to kill the process(only for existing packages)
3209 // so that we do not end up in a confused state while the user is still using the older
3210 // version of the application while the new one gets installed.
3211 IActivityManager am = ActivityManagerNative.getDefault();
3212 if (am != null) {
3213 try {
3214 am.killApplicationWithUid(pkgName, uid);
3215 } catch (RemoteException e) {
3216 }
3217 }
3218 }
3219
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003220 // The following constants are returned by cachePackageSharedLibsForAbiLI
3221 // to indicate if native shared libraries were found in the package.
3222 // Values are:
3223 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
3224 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
3225 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
3226 // in package (and not installed)
3227 //
3228 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
3229 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
3230 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003231
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003232 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
3233 // and automatically copy them to /data/data/<appname>/lib if present.
3234 //
3235 // NOTE: this method may throw an IOException if the library cannot
3236 // be copied to its final destination, e.g. if there isn't enough
3237 // room left on the data partition, or a ZipException if the package
3238 // file is malformed.
3239 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003240 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
3241 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003242 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
3243 final String apkLib = "lib/";
3244 final int apkLibLen = apkLib.length();
3245 final int cpuAbiLen = cpuAbi.length();
3246 final String libPrefix = "lib";
3247 final int libPrefixLen = libPrefix.length();
3248 final String libSuffix = ".so";
3249 final int libSuffixLen = libSuffix.length();
3250 boolean hasNativeLibraries = false;
3251 boolean installedNativeLibraries = false;
3252
3253 // the minimum length of a valid native shared library of the form
3254 // lib/<something>/lib<name>.so.
3255 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
3256
3257 ZipFile zipFile = new ZipFile(scanFile);
3258 Enumeration<ZipEntry> entries =
3259 (Enumeration<ZipEntry>) zipFile.entries();
3260
3261 while (entries.hasMoreElements()) {
3262 ZipEntry entry = entries.nextElement();
3263 // skip directories
3264 if (entry.isDirectory()) {
3265 continue;
3266 }
3267 String entryName = entry.getName();
3268
3269 // check that the entry looks like lib/<something>/lib<name>.so
3270 // here, but don't check the ABI just yet.
3271 //
3272 // - must be sufficiently long
3273 // - must end with libSuffix, i.e. ".so"
3274 // - must start with apkLib, i.e. "lib/"
3275 if (entryName.length() < minEntryLen ||
3276 !entryName.endsWith(libSuffix) ||
3277 !entryName.startsWith(apkLib) ) {
3278 continue;
3279 }
3280
3281 // file name must start with libPrefix, i.e. "lib"
3282 int lastSlash = entryName.lastIndexOf('/');
3283
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003284 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003285 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
3286 continue;
3287 }
3288
3289 hasNativeLibraries = true;
3290
3291 // check the cpuAbi now, between lib/ and /lib<name>.so
3292 //
3293 if (lastSlash != apkLibLen + cpuAbiLen ||
3294 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3295 continue;
3296
3297 // extract the library file name, ensure it doesn't contain
3298 // weird characters. we're guaranteed here that it doesn't contain
3299 // a directory separator though.
3300 String libFileName = entryName.substring(lastSlash+1);
3301 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3302 continue;
3303 }
3304
3305 installedNativeLibraries = true;
3306
3307 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3308 File.separator + libFileName;
3309 File sharedLibraryFile = new File(sharedLibraryFilePath);
3310 if (! sharedLibraryFile.exists() ||
3311 sharedLibraryFile.length() != entry.getSize() ||
3312 sharedLibraryFile.lastModified() != entry.getTime()) {
3313 if (Config.LOGD) {
3314 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003316 if (mInstaller == null) {
3317 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003318 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003319 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003320 sharedLibraryFile);
3321 }
3322 }
3323 if (!hasNativeLibraries)
3324 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3325
3326 if (!installedNativeLibraries)
3327 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3328
3329 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3330 }
3331
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003332 // Find the gdbserver executable program in a package at
3333 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3334 //
3335 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3336 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3337 //
3338 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3339 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3340 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3341 final String GDBSERVER = "gdbserver";
3342 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3343
3344 ZipFile zipFile = new ZipFile(scanFile);
3345 Enumeration<ZipEntry> entries =
3346 (Enumeration<ZipEntry>) zipFile.entries();
3347
3348 while (entries.hasMoreElements()) {
3349 ZipEntry entry = entries.nextElement();
3350 // skip directories
3351 if (entry.isDirectory()) {
3352 continue;
3353 }
3354 String entryName = entry.getName();
3355
3356 if (!entryName.equals(apkGdbServerPath)) {
3357 continue;
3358 }
3359
3360 String installGdbServerPath = installGdbServerDir.getPath() +
3361 "/" + GDBSERVER;
3362 File installGdbServerFile = new File(installGdbServerPath);
3363 if (! installGdbServerFile.exists() ||
3364 installGdbServerFile.length() != entry.getSize() ||
3365 installGdbServerFile.lastModified() != entry.getTime()) {
3366 if (Config.LOGD) {
3367 Log.d(TAG, "Caching gdbserver " + entry.getName());
3368 }
3369 if (mInstaller == null) {
3370 installGdbServerDir.mkdir();
3371 }
3372 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3373 installGdbServerFile);
3374 }
3375 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3376 }
3377 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3378 }
3379
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003380 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3381 // and copy them to /data/data/<appname>/lib.
3382 //
3383 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3384 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3385 // one if ro.product.cpu.abi2 is defined.
3386 //
3387 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3388 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003389 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003390 try {
3391 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3392
3393 // some architectures are capable of supporting several CPU ABIs
3394 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3395 // this is indicated by the definition of the ro.product.cpu.abi2
3396 // system property.
3397 //
3398 // only scan the package twice in case of ABI mismatch
3399 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003400 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003401 if (cpuAbi2 != null) {
3402 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003404
3405 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3406 Log.w(TAG,"Native ABI mismatch from package file");
3407 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003409
3410 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3411 cpuAbi = cpuAbi2;
3412 }
3413 }
3414
3415 // for debuggable packages, also extract gdbserver from lib/<abi>
3416 // into /data/data/<appname>/lib too.
3417 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3418 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3419 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3420 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3421 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003424 } catch (ZipException e) {
3425 Log.w(TAG, "Failed to extract data from package file", e);
3426 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003428 Log.w(TAG, "Failed to cache package shared libs", e);
3429 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003431 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 }
3433
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003434 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003436 File binaryDir,
3437 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 InputStream inputStream = zipFile.getInputStream(entry);
3439 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003440 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003442 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003443 // now need to be left as world readable and owned by the system.
3444 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3445 ! tempFile.setLastModified(entry.getTime()) ||
3446 FileUtils.setPermissions(tempFilePath,
3447 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003448 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003450 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003451 // Failed to properly write file.
3452 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003453 throw new IOException("Couldn't create cached binary "
3454 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003455 }
3456 } finally {
3457 inputStream.close();
3458 }
3459 }
3460
3461 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3462 if (chatty && Config.LOGD) Log.d(
3463 TAG, "Removing package " + pkg.applicationInfo.packageName );
3464
3465 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003466 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 mPackages.remove(pkg.applicationInfo.packageName);
3469 if (pkg.mPath != null) {
3470 mAppDirs.remove(pkg.mPath);
3471 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 PackageSetting ps = (PackageSetting)pkg.mExtras;
3474 if (ps != null && ps.sharedUser != null) {
3475 // XXX don't do this until the data is removed.
3476 if (false) {
3477 ps.sharedUser.packages.remove(ps);
3478 if (ps.sharedUser.packages.size() == 0) {
3479 // Remove.
3480 }
3481 }
3482 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 int N = pkg.providers.size();
3485 StringBuilder r = null;
3486 int i;
3487 for (i=0; i<N; i++) {
3488 PackageParser.Provider p = pkg.providers.get(i);
3489 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3490 p.info.name));
3491 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003493 /* The is another ContentProvider with this authority when
3494 * this app was installed so this authority is null,
3495 * Ignore it as we don't have to unregister the provider.
3496 */
3497 continue;
3498 }
3499 String names[] = p.info.authority.split(";");
3500 for (int j = 0; j < names.length; j++) {
3501 if (mProviders.get(names[j]) == p) {
3502 mProviders.remove(names[j]);
3503 if (chatty && Config.LOGD) Log.d(
3504 TAG, "Unregistered content provider: " + names[j] +
3505 ", className = " + p.info.name +
3506 ", isSyncable = " + p.info.isSyncable);
3507 }
3508 }
3509 if (chatty) {
3510 if (r == null) {
3511 r = new StringBuilder(256);
3512 } else {
3513 r.append(' ');
3514 }
3515 r.append(p.info.name);
3516 }
3517 }
3518 if (r != null) {
3519 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3520 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522 N = pkg.services.size();
3523 r = null;
3524 for (i=0; i<N; i++) {
3525 PackageParser.Service s = pkg.services.get(i);
3526 mServices.removeService(s);
3527 if (chatty) {
3528 if (r == null) {
3529 r = new StringBuilder(256);
3530 } else {
3531 r.append(' ');
3532 }
3533 r.append(s.info.name);
3534 }
3535 }
3536 if (r != null) {
3537 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3538 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 N = pkg.receivers.size();
3541 r = null;
3542 for (i=0; i<N; i++) {
3543 PackageParser.Activity a = pkg.receivers.get(i);
3544 mReceivers.removeActivity(a, "receiver");
3545 if (chatty) {
3546 if (r == null) {
3547 r = new StringBuilder(256);
3548 } else {
3549 r.append(' ');
3550 }
3551 r.append(a.info.name);
3552 }
3553 }
3554 if (r != null) {
3555 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 N = pkg.activities.size();
3559 r = null;
3560 for (i=0; i<N; i++) {
3561 PackageParser.Activity a = pkg.activities.get(i);
3562 mActivities.removeActivity(a, "activity");
3563 if (chatty) {
3564 if (r == null) {
3565 r = new StringBuilder(256);
3566 } else {
3567 r.append(' ');
3568 }
3569 r.append(a.info.name);
3570 }
3571 }
3572 if (r != null) {
3573 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003576 N = pkg.permissions.size();
3577 r = null;
3578 for (i=0; i<N; i++) {
3579 PackageParser.Permission p = pkg.permissions.get(i);
3580 boolean tree = false;
3581 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3582 if (bp == null) {
3583 tree = true;
3584 bp = mSettings.mPermissionTrees.get(p.info.name);
3585 }
3586 if (bp != null && bp.perm == p) {
3587 if (bp.type != BasePermission.TYPE_BUILTIN) {
3588 if (tree) {
3589 mSettings.mPermissionTrees.remove(p.info.name);
3590 } else {
3591 mSettings.mPermissions.remove(p.info.name);
3592 }
3593 } else {
3594 bp.perm = null;
3595 }
3596 if (chatty) {
3597 if (r == null) {
3598 r = new StringBuilder(256);
3599 } else {
3600 r.append(' ');
3601 }
3602 r.append(p.info.name);
3603 }
3604 }
3605 }
3606 if (r != null) {
3607 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3608 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003610 N = pkg.instrumentation.size();
3611 r = null;
3612 for (i=0; i<N; i++) {
3613 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003614 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 if (chatty) {
3616 if (r == null) {
3617 r = new StringBuilder(256);
3618 } else {
3619 r.append(' ');
3620 }
3621 r.append(a.info.name);
3622 }
3623 }
3624 if (r != null) {
3625 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3626 }
3627 }
3628 }
3629
3630 private static final boolean isPackageFilename(String name) {
3631 return name != null && name.endsWith(".apk");
3632 }
3633
3634 private void updatePermissionsLP() {
3635 // Make sure there are no dangling permission trees.
3636 Iterator<BasePermission> it = mSettings.mPermissionTrees
3637 .values().iterator();
3638 while (it.hasNext()) {
3639 BasePermission bp = it.next();
3640 if (bp.perm == null) {
3641 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3642 + " from package " + bp.sourcePackage);
3643 it.remove();
3644 }
3645 }
3646
3647 // Make sure all dynamic permissions have been assigned to a package,
3648 // and make sure there are no dangling permissions.
3649 it = mSettings.mPermissions.values().iterator();
3650 while (it.hasNext()) {
3651 BasePermission bp = it.next();
3652 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3653 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3654 + bp.name + " pkg=" + bp.sourcePackage
3655 + " info=" + bp.pendingInfo);
3656 if (bp.perm == null && bp.pendingInfo != null) {
3657 BasePermission tree = findPermissionTreeLP(bp.name);
3658 if (tree != null) {
3659 bp.perm = new PackageParser.Permission(tree.perm.owner,
3660 new PermissionInfo(bp.pendingInfo));
3661 bp.perm.info.packageName = tree.perm.info.packageName;
3662 bp.perm.info.name = bp.name;
3663 bp.uid = tree.uid;
3664 }
3665 }
3666 }
3667 if (bp.perm == null) {
3668 Log.w(TAG, "Removing dangling permission: " + bp.name
3669 + " from package " + bp.sourcePackage);
3670 it.remove();
3671 }
3672 }
3673
3674 // Now update the permissions for all packages, in particular
3675 // replace the granted permissions of the system packages.
3676 for (PackageParser.Package pkg : mPackages.values()) {
3677 grantPermissionsLP(pkg, false);
3678 }
3679 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003681 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3682 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3683 if (ps == null) {
3684 return;
3685 }
3686 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3687 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 if (replace) {
3690 ps.permissionsFixed = false;
3691 if (gp == ps) {
3692 gp.grantedPermissions.clear();
3693 gp.gids = mGlobalGids;
3694 }
3695 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 if (gp.gids == null) {
3698 gp.gids = mGlobalGids;
3699 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003701 final int N = pkg.requestedPermissions.size();
3702 for (int i=0; i<N; i++) {
3703 String name = pkg.requestedPermissions.get(i);
3704 BasePermission bp = mSettings.mPermissions.get(name);
3705 PackageParser.Permission p = bp != null ? bp.perm : null;
3706 if (false) {
3707 if (gp != ps) {
3708 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3709 + ": " + p);
3710 }
3711 }
3712 if (p != null) {
3713 final String perm = p.info.name;
3714 boolean allowed;
3715 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3716 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3717 allowed = true;
3718 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3719 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003720 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003722 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003723 == PackageManager.SIGNATURE_MATCH);
3724 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3725 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3726 // For updated system applications, the signatureOrSystem permission
3727 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003728 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3730 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3731 if(sysPs.grantedPermissions.contains(perm)) {
3732 allowed = true;
3733 } else {
3734 allowed = false;
3735 }
3736 } else {
3737 allowed = true;
3738 }
3739 }
3740 }
3741 } else {
3742 allowed = false;
3743 }
3744 if (false) {
3745 if (gp != ps) {
3746 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3747 }
3748 }
3749 if (allowed) {
3750 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3751 && ps.permissionsFixed) {
3752 // If this is an existing, non-system package, then
3753 // we can't add any new permissions to it.
3754 if (!gp.loadedPermissions.contains(perm)) {
3755 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003756 // Except... if this is a permission that was added
3757 // to the platform (note: need to only do this when
3758 // updating the platform).
3759 final int NP = PackageParser.NEW_PERMISSIONS.length;
3760 for (int ip=0; ip<NP; ip++) {
3761 final PackageParser.NewPermissionInfo npi
3762 = PackageParser.NEW_PERMISSIONS[ip];
3763 if (npi.name.equals(perm)
3764 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3765 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003766 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003767 + pkg.packageName);
3768 break;
3769 }
3770 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003771 }
3772 }
3773 if (allowed) {
3774 if (!gp.grantedPermissions.contains(perm)) {
3775 addedPermission = true;
3776 gp.grantedPermissions.add(perm);
3777 gp.gids = appendInts(gp.gids, bp.gids);
3778 }
3779 } else {
3780 Log.w(TAG, "Not granting permission " + perm
3781 + " to package " + pkg.packageName
3782 + " because it was previously installed without");
3783 }
3784 } else {
3785 Log.w(TAG, "Not granting permission " + perm
3786 + " to package " + pkg.packageName
3787 + " (protectionLevel=" + p.info.protectionLevel
3788 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3789 + ")");
3790 }
3791 } else {
3792 Log.w(TAG, "Unknown permission " + name
3793 + " in package " + pkg.packageName);
3794 }
3795 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003798 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3799 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 // This is the first that we have heard about this package, so the
3801 // permissions we have now selected are fixed until explicitly
3802 // changed.
3803 ps.permissionsFixed = true;
3804 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3805 }
3806 }
3807
3808 private final class ActivityIntentResolver
3809 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003810 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003812 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813 }
3814
Mihai Preda074edef2009-05-18 17:13:31 +02003815 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003817 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3819 }
3820
Mihai Predaeae850c2009-05-13 10:13:48 +02003821 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3822 ArrayList<PackageParser.Activity> packageActivities) {
3823 if (packageActivities == null) {
3824 return null;
3825 }
3826 mFlags = flags;
3827 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3828 int N = packageActivities.size();
3829 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3830 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003831
3832 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003833 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003834 intentFilters = packageActivities.get(i).intents;
3835 if (intentFilters != null && intentFilters.size() > 0) {
3836 listCut.add(intentFilters);
3837 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003838 }
3839 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3840 }
3841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 public final void addActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003843 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (SHOW_INFO || Config.LOGV) Log.v(
3845 TAG, " " + type + " " +
3846 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3847 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3848 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003849 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003850 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3851 if (SHOW_INFO || Config.LOGV) {
3852 Log.v(TAG, " IntentFilter:");
3853 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3854 }
3855 if (!intent.debugCheck()) {
3856 Log.w(TAG, "==> For Activity " + a.info.name);
3857 }
3858 addFilter(intent);
3859 }
3860 }
3861
3862 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003863 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 if (SHOW_INFO || Config.LOGV) Log.v(
3865 TAG, " " + type + " " +
3866 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3867 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3868 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003869 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3871 if (SHOW_INFO || Config.LOGV) {
3872 Log.v(TAG, " IntentFilter:");
3873 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3874 }
3875 removeFilter(intent);
3876 }
3877 }
3878
3879 @Override
3880 protected boolean allowFilterResult(
3881 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3882 ActivityInfo filterAi = filter.activity.info;
3883 for (int i=dest.size()-1; i>=0; i--) {
3884 ActivityInfo destAi = dest.get(i).activityInfo;
3885 if (destAi.name == filterAi.name
3886 && destAi.packageName == filterAi.packageName) {
3887 return false;
3888 }
3889 }
3890 return true;
3891 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 @Override
3894 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3895 int match) {
3896 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3897 return null;
3898 }
3899 final PackageParser.Activity activity = info.activity;
3900 if (mSafeMode && (activity.info.applicationInfo.flags
3901 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3902 return null;
3903 }
3904 final ResolveInfo res = new ResolveInfo();
3905 res.activityInfo = PackageParser.generateActivityInfo(activity,
3906 mFlags);
3907 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3908 res.filter = info;
3909 }
3910 res.priority = info.getPriority();
3911 res.preferredOrder = activity.owner.mPreferredOrder;
3912 //System.out.println("Result: " + res.activityInfo.className +
3913 // " = " + res.priority);
3914 res.match = match;
3915 res.isDefault = info.hasDefault;
3916 res.labelRes = info.labelRes;
3917 res.nonLocalizedLabel = info.nonLocalizedLabel;
3918 res.icon = info.icon;
3919 return res;
3920 }
3921
3922 @Override
3923 protected void sortResults(List<ResolveInfo> results) {
3924 Collections.sort(results, mResolvePrioritySorter);
3925 }
3926
3927 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003928 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003929 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003930 out.print(prefix); out.print(
3931 Integer.toHexString(System.identityHashCode(filter.activity)));
3932 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003933 out.println(filter.activity.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 }
3935
3936// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3937// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3938// final List<ResolveInfo> retList = Lists.newArrayList();
3939// while (i.hasNext()) {
3940// final ResolveInfo resolveInfo = i.next();
3941// if (isEnabledLP(resolveInfo.activityInfo)) {
3942// retList.add(resolveInfo);
3943// }
3944// }
3945// return retList;
3946// }
3947
3948 // Keys are String (activity class name), values are Activity.
3949 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3950 = new HashMap<ComponentName, PackageParser.Activity>();
3951 private int mFlags;
3952 }
3953
3954 private final class ServiceIntentResolver
3955 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003956 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003958 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 }
3960
Mihai Preda074edef2009-05-18 17:13:31 +02003961 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003963 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3965 }
3966
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003967 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3968 ArrayList<PackageParser.Service> packageServices) {
3969 if (packageServices == null) {
3970 return null;
3971 }
3972 mFlags = flags;
3973 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3974 int N = packageServices.size();
3975 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3976 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3977
3978 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3979 for (int i = 0; i < N; ++i) {
3980 intentFilters = packageServices.get(i).intents;
3981 if (intentFilters != null && intentFilters.size() > 0) {
3982 listCut.add(intentFilters);
3983 }
3984 }
3985 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3986 }
3987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003989 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 if (SHOW_INFO || Config.LOGV) Log.v(
3991 TAG, " " + (s.info.nonLocalizedLabel != null
3992 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3993 if (SHOW_INFO || Config.LOGV) Log.v(
3994 TAG, " Class=" + s.info.name);
3995 int NI = s.intents.size();
3996 int j;
3997 for (j=0; j<NI; j++) {
3998 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3999 if (SHOW_INFO || Config.LOGV) {
4000 Log.v(TAG, " IntentFilter:");
4001 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4002 }
4003 if (!intent.debugCheck()) {
4004 Log.w(TAG, "==> For Service " + s.info.name);
4005 }
4006 addFilter(intent);
4007 }
4008 }
4009
4010 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004011 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 if (SHOW_INFO || Config.LOGV) Log.v(
4013 TAG, " " + (s.info.nonLocalizedLabel != null
4014 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4015 if (SHOW_INFO || Config.LOGV) Log.v(
4016 TAG, " Class=" + s.info.name);
4017 int NI = s.intents.size();
4018 int j;
4019 for (j=0; j<NI; j++) {
4020 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4021 if (SHOW_INFO || Config.LOGV) {
4022 Log.v(TAG, " IntentFilter:");
4023 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4024 }
4025 removeFilter(intent);
4026 }
4027 }
4028
4029 @Override
4030 protected boolean allowFilterResult(
4031 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4032 ServiceInfo filterSi = filter.service.info;
4033 for (int i=dest.size()-1; i>=0; i--) {
4034 ServiceInfo destAi = dest.get(i).serviceInfo;
4035 if (destAi.name == filterSi.name
4036 && destAi.packageName == filterSi.packageName) {
4037 return false;
4038 }
4039 }
4040 return true;
4041 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 @Override
4044 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4045 int match) {
4046 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
4047 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4048 return null;
4049 }
4050 final PackageParser.Service service = info.service;
4051 if (mSafeMode && (service.info.applicationInfo.flags
4052 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4053 return null;
4054 }
4055 final ResolveInfo res = new ResolveInfo();
4056 res.serviceInfo = PackageParser.generateServiceInfo(service,
4057 mFlags);
4058 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4059 res.filter = filter;
4060 }
4061 res.priority = info.getPriority();
4062 res.preferredOrder = service.owner.mPreferredOrder;
4063 //System.out.println("Result: " + res.activityInfo.className +
4064 // " = " + res.priority);
4065 res.match = match;
4066 res.isDefault = info.hasDefault;
4067 res.labelRes = info.labelRes;
4068 res.nonLocalizedLabel = info.nonLocalizedLabel;
4069 res.icon = info.icon;
4070 return res;
4071 }
4072
4073 @Override
4074 protected void sortResults(List<ResolveInfo> results) {
4075 Collections.sort(results, mResolvePrioritySorter);
4076 }
4077
4078 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004079 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004081 out.print(prefix); out.print(
4082 Integer.toHexString(System.identityHashCode(filter.service)));
4083 out.print(' ');
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004084 out.println(filter.service.getComponentShortName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 }
4086
4087// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4088// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4089// final List<ResolveInfo> retList = Lists.newArrayList();
4090// while (i.hasNext()) {
4091// final ResolveInfo resolveInfo = (ResolveInfo) i;
4092// if (isEnabledLP(resolveInfo.serviceInfo)) {
4093// retList.add(resolveInfo);
4094// }
4095// }
4096// return retList;
4097// }
4098
4099 // Keys are String (activity class name), values are Activity.
4100 private final HashMap<ComponentName, PackageParser.Service> mServices
4101 = new HashMap<ComponentName, PackageParser.Service>();
4102 private int mFlags;
4103 };
4104
4105 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4106 new Comparator<ResolveInfo>() {
4107 public int compare(ResolveInfo r1, ResolveInfo r2) {
4108 int v1 = r1.priority;
4109 int v2 = r2.priority;
4110 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4111 if (v1 != v2) {
4112 return (v1 > v2) ? -1 : 1;
4113 }
4114 v1 = r1.preferredOrder;
4115 v2 = r2.preferredOrder;
4116 if (v1 != v2) {
4117 return (v1 > v2) ? -1 : 1;
4118 }
4119 if (r1.isDefault != r2.isDefault) {
4120 return r1.isDefault ? -1 : 1;
4121 }
4122 v1 = r1.match;
4123 v2 = r2.match;
4124 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4125 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4126 }
4127 };
4128
4129 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4130 new Comparator<ProviderInfo>() {
4131 public int compare(ProviderInfo p1, ProviderInfo p2) {
4132 final int v1 = p1.initOrder;
4133 final int v2 = p2.initOrder;
4134 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4135 }
4136 };
4137
4138 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
4139 IActivityManager am = ActivityManagerNative.getDefault();
4140 if (am != null) {
4141 try {
4142 final Intent intent = new Intent(action,
4143 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4144 if (extras != null) {
4145 intent.putExtras(extras);
4146 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004147 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 am.broadcastIntent(
4149 null, intent,
4150 null, null, 0, null, null, null, false, false);
4151 } catch (RemoteException ex) {
4152 }
4153 }
4154 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004155
4156 public String nextPackageToClean(String lastPackage) {
4157 synchronized (mPackages) {
4158 if (!mMediaMounted) {
4159 // If the external storage is no longer mounted at this point,
4160 // the caller may not have been able to delete all of this
4161 // packages files and can not delete any more. Bail.
4162 return null;
4163 }
4164 if (lastPackage != null) {
4165 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4166 }
4167 return mSettings.mPackagesToBeCleaned.size() > 0
4168 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4169 }
4170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004172 void schedulePackageCleaning(String packageName) {
4173 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4174 }
4175
4176 void startCleaningPackages() {
4177 synchronized (mPackages) {
4178 if (!mMediaMounted) {
4179 return;
4180 }
4181 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4182 return;
4183 }
4184 }
4185 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4186 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4187 IActivityManager am = ActivityManagerNative.getDefault();
4188 if (am != null) {
4189 try {
4190 am.startService(null, intent, null);
4191 } catch (RemoteException e) {
4192 }
4193 }
4194 }
4195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 private final class AppDirObserver extends FileObserver {
4197 public AppDirObserver(String path, int mask, boolean isrom) {
4198 super(path, mask);
4199 mRootDir = path;
4200 mIsRom = isrom;
4201 }
4202
4203 public void onEvent(int event, String path) {
4204 String removedPackage = null;
4205 int removedUid = -1;
4206 String addedPackage = null;
4207 int addedUid = -1;
4208
4209 synchronized (mInstallLock) {
4210 String fullPathStr = null;
4211 File fullPath = null;
4212 if (path != null) {
4213 fullPath = new File(mRootDir, path);
4214 fullPathStr = fullPath.getPath();
4215 }
4216
4217 if (Config.LOGV) Log.v(
4218 TAG, "File " + fullPathStr + " changed: "
4219 + Integer.toHexString(event));
4220
4221 if (!isPackageFilename(path)) {
4222 if (Config.LOGV) Log.v(
4223 TAG, "Ignoring change of non-package file: " + fullPathStr);
4224 return;
4225 }
4226
4227 if ((event&REMOVE_EVENTS) != 0) {
4228 synchronized (mInstallLock) {
4229 PackageParser.Package p = mAppDirs.get(fullPathStr);
4230 if (p != null) {
4231 removePackageLI(p, true);
4232 removedPackage = p.applicationInfo.packageName;
4233 removedUid = p.applicationInfo.uid;
4234 }
4235 }
4236 }
4237
4238 if ((event&ADD_EVENTS) != 0) {
4239 PackageParser.Package p = mAppDirs.get(fullPathStr);
4240 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004241 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
4243 PackageParser.PARSE_CHATTY |
4244 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08004245 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 if (p != null) {
4247 synchronized (mPackages) {
4248 grantPermissionsLP(p, false);
4249 }
4250 addedPackage = p.applicationInfo.packageName;
4251 addedUid = p.applicationInfo.uid;
4252 }
4253 }
4254 }
4255
4256 synchronized (mPackages) {
4257 mSettings.writeLP();
4258 }
4259 }
4260
4261 if (removedPackage != null) {
4262 Bundle extras = new Bundle(1);
4263 extras.putInt(Intent.EXTRA_UID, removedUid);
4264 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4265 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4266 }
4267 if (addedPackage != null) {
4268 Bundle extras = new Bundle(1);
4269 extras.putInt(Intent.EXTRA_UID, addedUid);
4270 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
4271 }
4272 }
4273
4274 private final String mRootDir;
4275 private final boolean mIsRom;
4276 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 /* Called when a downloaded package installation has been confirmed by the user */
4279 public void installPackage(
4280 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004281 installPackage(packageURI, observer, flags, null);
4282 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004283
Jacek Surazski65e13172009-04-28 15:26:38 +02004284 /* Called when a downloaded package installation has been confirmed by the user */
4285 public void installPackage(
4286 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4287 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 mContext.enforceCallingOrSelfPermission(
4289 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004290
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004291 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004292 msg.obj = new InstallParams(packageURI, observer, flags,
4293 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004294 mHandler.sendMessage(msg);
4295 }
4296
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004297 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 // Queue up an async operation since the package installation may take a little while.
4299 mHandler.post(new Runnable() {
4300 public void run() {
4301 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004302 // Result object to be returned
4303 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004304 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004305 res.uid = -1;
4306 res.pkg = null;
4307 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004308 args.doPreInstall(res.returnCode);
4309 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004310 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004311 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004312 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004313 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004315 if (args.observer != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004317 args.observer.packageInstalled(res.name, res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 } catch (RemoteException e) {
4319 Log.i(TAG, "Observer no longer exists.");
4320 }
4321 }
4322 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
4323 // call appears in the synchronized block above.
4324 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4325 res.removedInfo.sendBroadcast(false, true);
4326 Bundle extras = new Bundle(1);
4327 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004328 final boolean update = res.removedInfo.removedPackage != null;
4329 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004330 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4331 }
4332 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
4333 res.pkg.applicationInfo.packageName,
4334 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004335 if (update) {
4336 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
4337 res.pkg.applicationInfo.packageName,
4338 extras);
4339 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004340 if (res.removedInfo.args != null) {
4341 // Remove the replaced package's older resources safely now
4342 synchronized (mInstallLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004343 res.removedInfo.args.doPostDeleteLI(true);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004344 }
4345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004346 }
4347 Runtime.getRuntime().gc();
4348 }
4349 });
4350 }
4351
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004352 static final class InstallParams {
4353 final IPackageInstallObserver observer;
4354 int flags;
4355 final Uri packageURI;
4356 final String installerPackageName;
4357 InstallParams(Uri packageURI,
4358 IPackageInstallObserver observer, int flags,
4359 String installerPackageName) {
4360 this.packageURI = packageURI;
4361 this.flags = flags;
4362 this.observer = observer;
4363 this.installerPackageName = installerPackageName;
4364 }
4365
4366 public int getInstallLocation(IMediaContainerService imcs) {
4367 try {
4368 return imcs.getRecommendedInstallLocation(packageURI);
4369 } catch (RemoteException e) {
4370 }
4371 return -1;
4372 }
4373 };
4374
4375 private InstallArgs createInstallArgs(InstallParams params) {
4376 if (installOnSd(params.flags)) {
4377 return new SdInstallArgs(params);
4378 } else {
4379 return new FileInstallArgs(params);
4380 }
4381 }
4382
4383 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
4384 if (installOnSd(flags)) {
4385 return new SdInstallArgs(fullCodePath, fullResourcePath);
4386 } else {
4387 return new FileInstallArgs(fullCodePath, fullResourcePath);
4388 }
4389 }
4390
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004391 static abstract class InstallArgs {
4392 final IPackageInstallObserver observer;
4393 final int flags;
4394 final Uri packageURI;
4395 final String installerPackageName;
4396
4397 InstallArgs(Uri packageURI,
4398 IPackageInstallObserver observer, int flags,
4399 String installerPackageName) {
4400 this.packageURI = packageURI;
4401 this.flags = flags;
4402 this.observer = observer;
4403 this.installerPackageName = installerPackageName;
4404 }
4405
4406 abstract void createCopyFile();
4407 abstract int copyApk(IMediaContainerService imcs);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004408 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004409 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004410 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004411 abstract String getCodePath();
4412 abstract String getResourcePath();
4413 // Need installer lock especially for dex file removal.
4414 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004415 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004416 }
4417
4418 class FileInstallArgs extends InstallArgs {
4419 File installDir;
4420 String codeFileName;
4421 String resourceFileName;
4422
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004423 FileInstallArgs(InstallParams params) {
4424 super(params.packageURI, params.observer,
4425 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004426 }
4427
4428 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4429 super(null, null, 0, null);
4430 File codeFile = new File(fullCodePath);
4431 installDir = codeFile.getParentFile();
4432 codeFileName = fullCodePath;
4433 resourceFileName = fullResourcePath;
4434 }
4435
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004436 String getCodePath() {
4437 return codeFileName;
4438 }
4439
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004440 void createCopyFile() {
4441 boolean fwdLocked = isFwdLocked(flags);
4442 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4443 codeFileName = createTempPackageFile(installDir).getPath();
4444 resourceFileName = getResourcePathFromCodePath();
4445 }
4446
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004447 int copyApk(IMediaContainerService imcs) {
4448 // Get a ParcelFileDescriptor to write to the output file
4449 File codeFile = new File(codeFileName);
4450 ParcelFileDescriptor out = null;
4451 try {
4452 out = ParcelFileDescriptor.open(codeFile,
4453 ParcelFileDescriptor.MODE_READ_WRITE);
4454 } catch (FileNotFoundException e) {
4455 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4456 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4457 }
4458 // Copy the resource now
4459 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4460 try {
4461 if (imcs.copyResource(packageURI, out)) {
4462 ret = PackageManager.INSTALL_SUCCEEDED;
4463 }
4464 } catch (RemoteException e) {
4465 } finally {
4466 try { if (out != null) out.close(); } catch (IOException e) {}
4467 }
4468 return ret;
4469 }
4470
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004471 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004472 if (status != PackageManager.INSTALL_SUCCEEDED) {
4473 cleanUp();
4474 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004475 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004476 }
4477
4478 boolean doRename(int status, final String pkgName, String oldCodePath) {
4479 if (status != PackageManager.INSTALL_SUCCEEDED) {
4480 cleanUp();
4481 return false;
4482 } else {
4483 // Rename based on packageName
4484 File codeFile = new File(getCodePath());
4485 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4486 File desFile = new File(installDir, apkName + ".apk");
4487 if (!codeFile.renameTo(desFile)) {
4488 return false;
4489 }
4490 // Reset paths since the file has been renamed.
4491 codeFileName = desFile.getPath();
4492 resourceFileName = getResourcePathFromCodePath();
4493 // Set permissions
4494 if (!setPermissions(pkgName)) {
4495 // Failed setting permissions.
4496 return false;
4497 }
4498 return true;
4499 }
4500 }
4501
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004502 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004503 if (status != PackageManager.INSTALL_SUCCEEDED) {
4504 cleanUp();
4505 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004506 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004507 }
4508
4509 String getResourcePath() {
4510 return resourceFileName;
4511 }
4512
4513 String getResourcePathFromCodePath() {
4514 String codePath = getCodePath();
4515 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4516 String apkNameOnly = getApkName(codePath);
4517 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4518 } else {
4519 return codePath;
4520 }
4521 }
4522
4523 private boolean cleanUp() {
4524 boolean ret = true;
4525 String sourceDir = getCodePath();
4526 String publicSourceDir = getResourcePath();
4527 if (sourceDir != null) {
4528 File sourceFile = new File(sourceDir);
4529 if (!sourceFile.exists()) {
4530 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4531 ret = false;
4532 }
4533 // Delete application's code and resources
4534 sourceFile.delete();
4535 }
4536 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4537 final File publicSourceFile = new File(publicSourceDir);
4538 if (!publicSourceFile.exists()) {
4539 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4540 }
4541 if (publicSourceFile.exists()) {
4542 publicSourceFile.delete();
4543 }
4544 }
4545 return ret;
4546 }
4547
4548 void cleanUpResourcesLI() {
4549 String sourceDir = getCodePath();
4550 if (cleanUp() && mInstaller != null) {
4551 int retCode = mInstaller.rmdex(sourceDir);
4552 if (retCode < 0) {
4553 Log.w(TAG, "Couldn't remove dex file for package: "
4554 + " at location "
4555 + sourceDir + ", retcode=" + retCode);
4556 // we don't consider this to be a failure of the core package deletion
4557 }
4558 }
4559 }
4560
4561 private boolean setPermissions(String pkgName) {
4562 // TODO Do this in a more elegant way later on. for now just a hack
4563 if (!isFwdLocked(flags)) {
4564 final int filePermissions =
4565 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4566 |FileUtils.S_IROTH;
4567 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4568 if (retCode != 0) {
4569 Log.e(TAG, "Couldn't set new package file permissions for " +
4570 getCodePath()
4571 + ". The return code was: " + retCode);
4572 // TODO Define new internal error
4573 return false;
4574 }
4575 return true;
4576 }
4577 return true;
4578 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004579
4580 boolean doPostDeleteLI(boolean delete) {
4581 cleanUpResourcesLI();
4582 return true;
4583 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004584 }
4585
4586 class SdInstallArgs extends InstallArgs {
4587 String cid;
4588 String cachePath;
4589 static final String RES_FILE_NAME = "pkg.apk";
4590
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004591 SdInstallArgs(InstallParams params) {
4592 super(params.packageURI, params.observer,
4593 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004594 }
4595
4596 SdInstallArgs(String fullCodePath, String fullResourcePath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004597 super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004598 // Extract cid from fullCodePath
4599 int eidx = fullCodePath.lastIndexOf("/");
4600 String subStr1 = fullCodePath.substring(0, eidx);
4601 int sidx = subStr1.lastIndexOf("/");
4602 cid = subStr1.substring(sidx+1, eidx);
4603 cachePath = subStr1;
4604 }
4605
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004606 SdInstallArgs(String cid) {
4607 super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
4608 this.cid = cid;
4609 }
4610
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004611 void createCopyFile() {
4612 cid = getTempContainerId();
4613 }
4614
4615 int copyApk(IMediaContainerService imcs) {
4616 try {
4617 cachePath = imcs.copyResourceToContainer(
4618 packageURI, cid,
4619 getEncryptKey(), RES_FILE_NAME);
4620 } catch (RemoteException e) {
4621 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004622 return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
4623 PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004624 }
4625
4626 @Override
4627 String getCodePath() {
4628 return cachePath + "/" + RES_FILE_NAME;
4629 }
4630
4631 @Override
4632 String getResourcePath() {
4633 return cachePath + "/" + RES_FILE_NAME;
4634 }
4635
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004636 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004637 if (status != PackageManager.INSTALL_SUCCEEDED) {
4638 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004639 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004640 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004641 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004642 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004643 cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004644 if (cachePath == null) {
4645 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4646 }
4647 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004648 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004649 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004650 }
4651
4652 boolean doRename(int status, final String pkgName,
4653 String oldCodePath) {
4654 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004655 String newCachePath = null;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004656 final int RENAME_FAILED = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004657 final int MOUNT_FAILED = 2;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004658 final int PASS = 4;
4659 int errCode = RENAME_FAILED;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004660 String errMsg = "RENAME_FAILED";
4661 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004662 if (mounted) {
4663 // Unmount the container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004664 if (!PackageHelper.unMountSdDir(cid)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004665 Log.i(TAG, "Failed to unmount " + cid + " before renaming");
4666 return false;
4667 }
4668 mounted = false;
4669 }
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004670 if (PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004671 errCode = MOUNT_FAILED;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004672 errMsg = "MOUNT_FAILED";
4673 if ((newCachePath = PackageHelper.mountSdDir(newCacheId,
4674 getEncryptKey(), Process.SYSTEM_UID)) != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004675 errCode = PASS;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004676 errMsg = "PASS";
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004677 }
4678 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004679 if (errCode != PASS) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004680 Log.i(TAG, "Failed to rename " + cid + " to " + newCacheId +
4681 " at path: " + cachePath + " to new path: " + newCachePath +
4682 "err = " + errMsg);
4683 // Mount old container?
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004684 return false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004685 } else {
4686 Log.i(TAG, "Succesfully renamed " + cid + " to " + newCacheId +
4687 " at path: " + cachePath + " to new path: " + newCachePath);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004688 }
4689 cid = newCacheId;
4690 cachePath = newCachePath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004691 return true;
4692 }
4693
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004694 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004695 if (status != PackageManager.INSTALL_SUCCEEDED) {
4696 cleanUp();
4697 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004698 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004699 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004700 PackageHelper.mountSdDir(cid,
4701 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004702 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004703 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004704 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004705 }
4706
4707 private void cleanUp() {
4708 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004709 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004710 }
4711
4712 void cleanUpResourcesLI() {
4713 String sourceFile = getCodePath();
4714 // Remove dex file
4715 if (mInstaller != null) {
4716 int retCode = mInstaller.rmdex(sourceFile.toString());
4717 if (retCode < 0) {
4718 Log.w(TAG, "Couldn't remove dex file for package: "
4719 + " at location "
4720 + sourceFile.toString() + ", retcode=" + retCode);
4721 // we don't consider this to be a failure of the core package deletion
4722 }
4723 }
4724 cleanUp();
4725 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004726
4727 boolean matchContainer(String app) {
4728 if (cid.startsWith(app)) {
4729 return true;
4730 }
4731 return false;
4732 }
4733
4734 String getPackageName() {
4735 int idx = cid.lastIndexOf("-");
4736 if (idx == -1) {
4737 return cid;
4738 }
4739 return cid.substring(0, idx);
4740 }
4741
4742 boolean doPostDeleteLI(boolean delete) {
4743 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004744 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004745 if (mounted) {
4746 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08004747 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004748 }
4749 if (ret && delete) {
4750 cleanUpResourcesLI();
4751 }
4752 return ret;
4753 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004754 };
4755
4756 // Utility method used to create code paths based on package name and available index.
4757 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
4758 String idxStr = "";
4759 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004760 // Fall back to default value of idx=1 if prefix is not
4761 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004762 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004763 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004764 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004765 if (subStr.endsWith(suffix)) {
4766 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004767 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004768 // If oldCodePath already contains prefix find out the
4769 // ending index to either increment or decrement.
4770 int sidx = subStr.lastIndexOf(prefix);
4771 if (sidx != -1) {
4772 subStr = subStr.substring(sidx + prefix.length());
4773 if (subStr != null) {
4774 if (subStr.startsWith("-")) {
4775 subStr = subStr.substring(1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004776 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004777 try {
4778 idx = Integer.parseInt(subStr);
4779 if (idx <= 1) {
4780 idx++;
4781 } else {
4782 idx--;
4783 }
4784 } catch(NumberFormatException e) {
4785 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004786 }
4787 }
4788 }
4789 idxStr = "-" + Integer.toString(idx);
4790 return prefix + idxStr;
4791 }
4792
4793 // Utility method that returns the relative package path with respect
4794 // to the installation directory. Like say for /data/data/com.test-1.apk
4795 // string com.test-1 is returned.
4796 static String getApkName(String codePath) {
4797 if (codePath == null) {
4798 return null;
4799 }
4800 int sidx = codePath.lastIndexOf("/");
4801 int eidx = codePath.lastIndexOf(".");
4802 if (eidx == -1) {
4803 eidx = codePath.length();
4804 } else if (eidx == 0) {
4805 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
4806 return null;
4807 }
4808 return codePath.substring(sidx+1, eidx);
4809 }
4810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 class PackageInstalledInfo {
4812 String name;
4813 int uid;
4814 PackageParser.Package pkg;
4815 int returnCode;
4816 PackageRemovedInfo removedInfo;
4817 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004819 /*
4820 * Install a non-existing package.
4821 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004822 private void installNewPackageLI(PackageParser.Package pkg,
4823 int parseFlags,
4824 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004825 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08004827 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004828 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08004829
4830 if (useEncryptedFilesystemForPackage(pkg)) {
4831 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
4832 } else {
4833 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
4834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004835 res.name = pkgName;
4836 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004837 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004838 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004839 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 + " without first uninstalling.");
4841 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4842 return;
4843 }
4844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004846 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004848 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4850 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4851 }
4852 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004853 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004854 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 res);
4856 // delete the partially installed application. the data directory will have to be
4857 // restored if it was already existing
4858 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4859 // remove package from internal structures. Note that we want deletePackageX to
4860 // delete the package data and cache directories that it created in
4861 // scanPackageLocked, unless those directories existed before we even tried to
4862 // install.
4863 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004864 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
4866 res.removedInfo);
4867 }
4868 }
4869 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004870
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004871 private void replacePackageLI(PackageParser.Package pkg,
4872 int parseFlags,
4873 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004874 String installerPackageName, PackageInstalledInfo res) {
4875
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004876 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004877 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 // First find the old package info and check signatures
4879 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004880 oldPackage = mPackages.get(pkgName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004881 if (checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004882 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4884 return;
4885 }
4886 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004887 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004888 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004889 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004890 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004891 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 }
4893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004896 PackageParser.Package pkg,
4897 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004898 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 PackageParser.Package newPackage = null;
4900 String pkgName = deletedPackage.packageName;
4901 boolean deletedPkg = true;
4902 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004903
Jacek Surazski65e13172009-04-28 15:26:38 +02004904 String oldInstallerPackageName = null;
4905 synchronized (mPackages) {
4906 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
4907 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004908
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004909 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004910 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004911 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 res.removedInfo)) {
4913 // If the existing package was'nt successfully deleted
4914 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4915 deletedPkg = false;
4916 } else {
4917 // Successfully deleted the old package. Now proceed with re-installation
4918 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004919 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004920 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004921 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004922 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4923 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08004924 }
4925 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004926 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004927 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004928 res);
4929 updatedSettings = true;
4930 }
4931 }
4932
4933 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4934 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004935 // were keeping around in case we needed them (see below) can now be deleted.
4936 // This info will be set on the res.removedInfo to clean up later on as post
4937 // install action.
4938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 //update signature on the new package setting
4940 //this should always succeed, since we checked the
4941 //signature earlier.
4942 synchronized(mPackages) {
4943 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4944 parseFlags, true);
4945 }
4946 } else {
4947 // remove package from internal structures. Note that we want deletePackageX to
4948 // delete the package data and cache directories that it created in
4949 // scanPackageLocked, unless those directories existed before we even tried to
4950 // install.
4951 if(updatedSettings) {
4952 deletePackageLI(
4953 pkgName, true,
4954 PackageManager.DONT_DELETE_DATA,
4955 res.removedInfo);
4956 }
4957 // Since we failed to install the new package we need to restore the old
4958 // package that we deleted.
4959 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004960 File restoreFile = new File(deletedPackage.mPath);
4961 if (restoreFile == null) {
4962 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4963 return;
4964 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004965 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4966 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004967 // Parse old package
4968 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
4969 scanPackageLI(restoreFile, parseFlags, scanMode);
4970 synchronized (mPackages) {
4971 grantPermissionsLP(deletedPackage, false);
4972 mSettings.writeLP();
4973 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004974 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4975 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 }
4978 }
4979 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004982 PackageParser.Package pkg,
4983 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004984 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 PackageParser.Package newPackage = null;
4986 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004987 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 PackageParser.PARSE_IS_SYSTEM;
4989 String packageName = deletedPackage.packageName;
4990 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4991 if (packageName == null) {
4992 Log.w(TAG, "Attempt to delete null packageName.");
4993 return;
4994 }
4995 PackageParser.Package oldPkg;
4996 PackageSetting oldPkgSetting;
4997 synchronized (mPackages) {
4998 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004999 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005000 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5001 (oldPkgSetting == null)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005002 Log.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005003 return;
5004 }
5005 }
5006 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5007 res.removedInfo.removedPackage = packageName;
5008 // Remove existing system package
5009 removePackageLI(oldPkg, true);
5010 synchronized (mPackages) {
5011 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
5012 }
5013
5014 // Successfully disabled the old package. Now proceed with re-installation
5015 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5016 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005017 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005019 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5021 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5022 }
5023 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005024 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 updatedSettings = true;
5026 }
5027
5028 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
5029 //update signature on the new package setting
5030 //this should always succeed, since we checked the
5031 //signature earlier.
5032 synchronized(mPackages) {
5033 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
5034 parseFlags, true);
5035 }
5036 } else {
5037 // Re installation failed. Restore old information
5038 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005039 if (newPackage != null) {
5040 removePackageLI(newPackage, true);
5041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005042 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005043 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005044 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07005045 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005046 // Restore the old system information in Settings
5047 synchronized(mPackages) {
5048 if(updatedSettings) {
5049 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005050 mSettings.setInstallerPackageName(packageName,
5051 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 }
5053 mSettings.writeLP();
5054 }
5055 }
5056 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005057
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005058 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005059 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005060 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 synchronized (mPackages) {
5062 //write settings. the installStatus will be incomplete at this stage.
5063 //note that the new package setting would have already been
5064 //added to mPackages. It hasn't been persisted yet.
5065 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5066 mSettings.writeLP();
5067 }
5068
5069 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005070 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5071 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005073 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5075 return;
5076 }
5077 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005078 res.returnCode = setPermissionsLI(newPackage);
5079 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5080 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005082 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 }
5084 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5085 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005086 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 }
5088 }
5089
5090 synchronized (mPackages) {
5091 grantPermissionsLP(newPackage, true);
5092 res.name = pkgName;
5093 res.uid = newPackage.applicationInfo.uid;
5094 res.pkg = newPackage;
5095 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005096 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5098 //to update install status
5099 mSettings.writeLP();
5100 }
5101 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005102
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005103 private void installPackageLI(InstallArgs args,
5104 boolean newInstall, PackageInstalledInfo res) {
5105 int pFlags = args.flags;
5106 String installerPackageName = args.installerPackageName;
5107 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005108 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005109 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005110 boolean replace = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005111 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
5112 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005113 // Result object to be returned
5114 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5115
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005116 // Retrieve PackageSettings and parse package
5117 int parseFlags = PackageParser.PARSE_CHATTY |
5118 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5119 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5120 parseFlags |= mDefParseFlags;
5121 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5122 pp.setSeparateProcesses(mSeparateProcesses);
5123 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5124 null, mMetrics, parseFlags);
5125 if (pkg == null) {
5126 res.returnCode = pp.getParseError();
5127 return;
5128 }
5129 String pkgName = res.name = pkg.packageName;
5130 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5131 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5132 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5133 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005135 }
5136 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5137 res.returnCode = pp.getParseError();
5138 return;
5139 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005140 // Get rid of all references to package scan path via parser.
5141 pp = null;
5142 String oldCodePath = null;
5143 boolean systemApp = false;
5144 synchronized (mPackages) {
5145 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005146 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5147 String oldName = mSettings.mRenamedPackages.get(pkgName);
5148 if (oldName != null && oldName.equals(pkg.mOriginalPackage)
5149 && mPackages.containsKey(oldName)) {
5150 // This package is derived from an original package,
5151 // and this device has been updating from that original
5152 // name. We must continue using the original name, so
5153 // rename the new package here.
5154 pkg.setPackageName(pkg.mOriginalPackage);
5155 pkgName = pkg.packageName;
5156 replace = true;
5157 } else if (mPackages.containsKey(pkgName)) {
5158 // This package, under its official name, already exists
5159 // on the device; we should replace it.
5160 replace = true;
5161 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005162 }
5163 PackageSetting ps = mSettings.mPackages.get(pkgName);
5164 if (ps != null) {
5165 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5166 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5167 systemApp = (ps.pkg.applicationInfo.flags &
5168 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005169 }
5170 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005171 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005172
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005173 if (systemApp && onSd) {
5174 // Disable updates to system apps on sdcard
5175 Log.w(TAG, "Cannot install updates to system apps on sdcard");
5176 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5177 return;
5178 }
5179 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5180 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5181 return;
5182 }
5183 // Set application objects path explicitly after the rename
5184 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005185 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005186 replacePackageLI(pkg, parseFlags, scanMode,
5187 installerPackageName, res);
5188 } else {
5189 installNewPackageLI(pkg, parseFlags, scanMode,
5190 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 }
5192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005193
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005194 private int setPermissionsLI(PackageParser.Package newPackage) {
5195 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005196 int retCode = 0;
5197 // TODO Gross hack but fix later. Ideally move this to be a post installation
5198 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005199 if ((newPackage.applicationInfo.flags
5200 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
5201 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 try {
5203 extractPublicFiles(newPackage, destResourceFile);
5204 } catch (IOException e) {
5205 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
5206 " forward-locked app.");
5207 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5208 } finally {
5209 //TODO clean up the extracted public files
5210 }
5211 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005212 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 newPackage.applicationInfo.uid);
5214 } else {
5215 final int filePermissions =
5216 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005217 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 newPackage.applicationInfo.uid);
5219 }
5220 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005221 // The permissions on the resource file was set when it was copied for
5222 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005223 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005226 Log.e(TAG, "Couldn't set new package file permissions for " +
5227 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005229 // TODO Define new internal error
5230 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005231 }
5232 return PackageManager.INSTALL_SUCCEEDED;
5233 }
5234
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005235 private boolean isForwardLocked(PackageParser.Package pkg) {
5236 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237 }
5238
5239 private void extractPublicFiles(PackageParser.Package newPackage,
5240 File publicZipFile) throws IOException {
5241 final ZipOutputStream publicZipOutStream =
5242 new ZipOutputStream(new FileOutputStream(publicZipFile));
5243 final ZipFile privateZip = new ZipFile(newPackage.mPath);
5244
5245 // Copy manifest, resources.arsc and res directory to public zip
5246
5247 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
5248 while (privateZipEntries.hasMoreElements()) {
5249 final ZipEntry zipEntry = privateZipEntries.nextElement();
5250 final String zipEntryName = zipEntry.getName();
5251 if ("AndroidManifest.xml".equals(zipEntryName)
5252 || "resources.arsc".equals(zipEntryName)
5253 || zipEntryName.startsWith("res/")) {
5254 try {
5255 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
5256 } catch (IOException e) {
5257 try {
5258 publicZipOutStream.close();
5259 throw e;
5260 } finally {
5261 publicZipFile.delete();
5262 }
5263 }
5264 }
5265 }
5266
5267 publicZipOutStream.close();
5268 FileUtils.setPermissions(
5269 publicZipFile.getAbsolutePath(),
5270 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
5271 -1, -1);
5272 }
5273
5274 private static void copyZipEntry(ZipEntry zipEntry,
5275 ZipFile inZipFile,
5276 ZipOutputStream outZipStream) throws IOException {
5277 byte[] buffer = new byte[4096];
5278 int num;
5279
5280 ZipEntry newEntry;
5281 if (zipEntry.getMethod() == ZipEntry.STORED) {
5282 // Preserve the STORED method of the input entry.
5283 newEntry = new ZipEntry(zipEntry);
5284 } else {
5285 // Create a new entry so that the compressed len is recomputed.
5286 newEntry = new ZipEntry(zipEntry.getName());
5287 }
5288 outZipStream.putNextEntry(newEntry);
5289
5290 InputStream data = inZipFile.getInputStream(zipEntry);
5291 while ((num = data.read(buffer)) > 0) {
5292 outZipStream.write(buffer, 0, num);
5293 }
5294 outZipStream.flush();
5295 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005297 private void deleteTempPackageFiles() {
5298 FilenameFilter filter = new FilenameFilter() {
5299 public boolean accept(File dir, String name) {
5300 return name.startsWith("vmdl") && name.endsWith(".tmp");
5301 }
5302 };
5303 String tmpFilesList[] = mAppInstallDir.list(filter);
5304 if(tmpFilesList == null) {
5305 return;
5306 }
5307 for(int i = 0; i < tmpFilesList.length; i++) {
5308 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
5309 tmpFile.delete();
5310 }
5311 }
5312
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005313 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 File tmpPackageFile;
5315 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005316 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 } catch (IOException e) {
5318 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
5319 return null;
5320 }
5321 try {
5322 FileUtils.setPermissions(
5323 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
5324 -1, -1);
5325 } catch (IOException e) {
5326 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
5327 return null;
5328 }
5329 return tmpPackageFile;
5330 }
5331
5332 public void deletePackage(final String packageName,
5333 final IPackageDeleteObserver observer,
5334 final int flags) {
5335 mContext.enforceCallingOrSelfPermission(
5336 android.Manifest.permission.DELETE_PACKAGES, null);
5337 // Queue up an async operation since the package deletion may take a little while.
5338 mHandler.post(new Runnable() {
5339 public void run() {
5340 mHandler.removeCallbacks(this);
5341 final boolean succeded = deletePackageX(packageName, true, true, flags);
5342 if (observer != null) {
5343 try {
5344 observer.packageDeleted(succeded);
5345 } catch (RemoteException e) {
5346 Log.i(TAG, "Observer no longer exists.");
5347 } //end catch
5348 } //end if
5349 } //end run
5350 });
5351 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 /**
5354 * This method is an internal method that could be get invoked either
5355 * to delete an installed package or to clean up a failed installation.
5356 * After deleting an installed package, a broadcast is sent to notify any
5357 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005358 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 * installation wouldn't have sent the initial broadcast either
5360 * The key steps in deleting a package are
5361 * deleting the package information in internal structures like mPackages,
5362 * deleting the packages base directories through installd
5363 * updating mSettings to reflect current status
5364 * persisting settings for later use
5365 * sending a broadcast if necessary
5366 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005367 private boolean deletePackageX(String packageName, boolean sendBroadCast,
5368 boolean deleteCodeAndResources, int flags) {
5369 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07005370 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005371
5372 synchronized (mInstallLock) {
5373 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
5374 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07005377 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
5378 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
5379
5380 // If the removed package was a system update, the old system packaged
5381 // was re-enabled; we need to broadcast this information
5382 if (systemUpdate) {
5383 Bundle extras = new Bundle(1);
5384 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
5385 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5386
5387 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
5388 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
5389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005391 // Delete the resources here after sending the broadcast to let
5392 // other processes clean up before deleting resources.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005393 if (info.args != null) {
5394 synchronized (mInstallLock) {
5395 info.args.doPostDeleteLI(deleteCodeAndResources);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005396 }
5397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 return res;
5399 }
5400
5401 static class PackageRemovedInfo {
5402 String removedPackage;
5403 int uid = -1;
5404 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07005405 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005406 // Clean up resources deleted packages.
5407 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07005408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005409 void sendBroadcast(boolean fullRemove, boolean replacing) {
5410 Bundle extras = new Bundle(1);
5411 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
5412 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
5413 if (replacing) {
5414 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5415 }
5416 if (removedPackage != null) {
5417 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
5418 }
5419 if (removedUid >= 0) {
5420 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5421 }
5422 }
5423 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 /*
5426 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5427 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005428 * 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 -08005429 * delete a partially installed application.
5430 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005431 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005432 int flags) {
5433 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005434 if (outInfo != null) {
5435 outInfo.removedPackage = packageName;
5436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005437 removePackageLI(p, true);
5438 // Retrieve object to delete permissions for shared user later on
5439 PackageSetting deletedPs;
5440 synchronized (mPackages) {
5441 deletedPs = mSettings.mPackages.get(packageName);
5442 }
5443 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005444 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005445 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005446 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 if (retCode < 0) {
5448 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5449 + packageName + ", retcode=" + retCode);
5450 // we don't consider this to be a failure of the core package deletion
5451 }
5452 } else {
5453 //for emulator
5454 PackageParser.Package pkg = mPackages.get(packageName);
5455 File dataDir = new File(pkg.applicationInfo.dataDir);
5456 dataDir.delete();
5457 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005458 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005460 if (outInfo != null) {
5461 outInfo.removedUid = mSettings.removePackageLP(packageName);
5462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 }
5464 }
5465 synchronized (mPackages) {
5466 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5467 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005468 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 }
5470 // Save settings now
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005471 mSettings.writeLP();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005472 }
5473 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 /*
5476 * Tries to delete system package.
5477 */
5478 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005479 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005480 ApplicationInfo applicationInfo = p.applicationInfo;
5481 //applicable for non-partially installed applications only
5482 if (applicationInfo == null) {
5483 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5484 return false;
5485 }
5486 PackageSetting ps = null;
5487 // Confirm if the system package has been updated
5488 // An updated system app can be deleted. This will also have to restore
5489 // the system pkg from system partition
5490 synchronized (mPackages) {
5491 ps = mSettings.getDisabledSystemPkg(p.packageName);
5492 }
5493 if (ps == null) {
5494 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5495 return false;
5496 } else {
5497 Log.i(TAG, "Deleting system pkg from data partition");
5498 }
5499 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005500 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005501 boolean deleteCodeAndResources = false;
5502 if (ps.versionCode < p.mVersionCode) {
5503 // Delete code and resources for downgrades
5504 deleteCodeAndResources = true;
5505 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5506 flags &= ~PackageManager.DONT_DELETE_DATA;
5507 }
5508 } else {
5509 // Preserve data by setting flag
5510 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5511 flags |= PackageManager.DONT_DELETE_DATA;
5512 }
5513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5515 if (!ret) {
5516 return false;
5517 }
5518 synchronized (mPackages) {
5519 // Reinstate the old system package
5520 mSettings.enableSystemPackageLP(p.packageName);
5521 }
5522 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005523 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005524 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005525 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 if (newPkg == null) {
5528 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5529 return false;
5530 }
5531 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005532 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 mSettings.writeLP();
5534 }
5535 return true;
5536 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5539 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5540 ApplicationInfo applicationInfo = p.applicationInfo;
5541 if (applicationInfo == null) {
5542 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5543 return false;
5544 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005545 if (outInfo != null) {
5546 outInfo.uid = applicationInfo.uid;
5547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548
5549 // Delete package data from internal structures and also remove data if flag is set
5550 removePackageDataLI(p, outInfo, flags);
5551
5552 // Delete application code and resources
5553 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005554 // TODO can pick up from PackageSettings as well
5555 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005556 PackageManager.INSTALL_EXTERNAL : 0;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005557 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5558 PackageManager.INSTALL_FORWARD_LOCK : 0;
5559 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005560 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005561 }
5562 return true;
5563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 /*
5566 * This method handles package deletion in general
5567 */
5568 private boolean deletePackageLI(String packageName,
5569 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5570 if (packageName == null) {
5571 Log.w(TAG, "Attempt to delete null packageName.");
5572 return false;
5573 }
5574 PackageParser.Package p;
5575 boolean dataOnly = false;
5576 synchronized (mPackages) {
5577 p = mPackages.get(packageName);
5578 if (p == null) {
5579 //this retrieves partially installed apps
5580 dataOnly = true;
5581 PackageSetting ps = mSettings.mPackages.get(packageName);
5582 if (ps == null) {
5583 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5584 return false;
5585 }
5586 p = ps.pkg;
5587 }
5588 }
5589 if (p == null) {
5590 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5591 return false;
5592 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 if (dataOnly) {
5595 // Delete application data first
5596 removePackageDataLI(p, outInfo, flags);
5597 return true;
5598 }
5599 // At this point the package should have ApplicationInfo associated with it
5600 if (p.applicationInfo == null) {
5601 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5602 return false;
5603 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005604 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5606 Log.i(TAG, "Removing system package:"+p.packageName);
5607 // When an updated system application is deleted we delete the existing resources as well and
5608 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005609 ret = deleteSystemPackageLI(p, flags, outInfo);
5610 } else {
5611 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005612 // Kill application pre-emptively especially for apps on sd.
5613 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005614 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005616 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005619 public void clearApplicationUserData(final String packageName,
5620 final IPackageDataObserver observer) {
5621 mContext.enforceCallingOrSelfPermission(
5622 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
5623 // Queue up an async operation since the package deletion may take a little while.
5624 mHandler.post(new Runnable() {
5625 public void run() {
5626 mHandler.removeCallbacks(this);
5627 final boolean succeeded;
5628 synchronized (mInstallLock) {
5629 succeeded = clearApplicationUserDataLI(packageName);
5630 }
5631 if (succeeded) {
5632 // invoke DeviceStorageMonitor's update method to clear any notifications
5633 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
5634 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
5635 if (dsm != null) {
5636 dsm.updateMemory();
5637 }
5638 }
5639 if(observer != null) {
5640 try {
5641 observer.onRemoveCompleted(packageName, succeeded);
5642 } catch (RemoteException e) {
5643 Log.i(TAG, "Observer no longer exists.");
5644 }
5645 } //end if observer
5646 } //end run
5647 });
5648 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 private boolean clearApplicationUserDataLI(String packageName) {
5651 if (packageName == null) {
5652 Log.w(TAG, "Attempt to delete null packageName.");
5653 return false;
5654 }
5655 PackageParser.Package p;
5656 boolean dataOnly = false;
5657 synchronized (mPackages) {
5658 p = mPackages.get(packageName);
5659 if(p == null) {
5660 dataOnly = true;
5661 PackageSetting ps = mSettings.mPackages.get(packageName);
5662 if((ps == null) || (ps.pkg == null)) {
5663 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5664 return false;
5665 }
5666 p = ps.pkg;
5667 }
5668 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005669 boolean useEncryptedFSDir = false;
5670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 if(!dataOnly) {
5672 //need to check this only for fully installed applications
5673 if (p == null) {
5674 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5675 return false;
5676 }
5677 final ApplicationInfo applicationInfo = p.applicationInfo;
5678 if (applicationInfo == null) {
5679 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5680 return false;
5681 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005682 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 }
5684 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005685 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 if (retCode < 0) {
5687 Log.w(TAG, "Couldn't remove cache files for package: "
5688 + packageName);
5689 return false;
5690 }
5691 }
5692 return true;
5693 }
5694
5695 public void deleteApplicationCacheFiles(final String packageName,
5696 final IPackageDataObserver observer) {
5697 mContext.enforceCallingOrSelfPermission(
5698 android.Manifest.permission.DELETE_CACHE_FILES, null);
5699 // Queue up an async operation since the package deletion may take a little while.
5700 mHandler.post(new Runnable() {
5701 public void run() {
5702 mHandler.removeCallbacks(this);
5703 final boolean succeded;
5704 synchronized (mInstallLock) {
5705 succeded = deleteApplicationCacheFilesLI(packageName);
5706 }
5707 if(observer != null) {
5708 try {
5709 observer.onRemoveCompleted(packageName, succeded);
5710 } catch (RemoteException e) {
5711 Log.i(TAG, "Observer no longer exists.");
5712 }
5713 } //end if observer
5714 } //end run
5715 });
5716 }
5717
5718 private boolean deleteApplicationCacheFilesLI(String packageName) {
5719 if (packageName == null) {
5720 Log.w(TAG, "Attempt to delete null packageName.");
5721 return false;
5722 }
5723 PackageParser.Package p;
5724 synchronized (mPackages) {
5725 p = mPackages.get(packageName);
5726 }
5727 if (p == null) {
5728 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5729 return false;
5730 }
5731 final ApplicationInfo applicationInfo = p.applicationInfo;
5732 if (applicationInfo == null) {
5733 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5734 return false;
5735 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005736 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005737 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005738 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005739 if (retCode < 0) {
5740 Log.w(TAG, "Couldn't remove cache files for package: "
5741 + packageName);
5742 return false;
5743 }
5744 }
5745 return true;
5746 }
5747
5748 public void getPackageSizeInfo(final String packageName,
5749 final IPackageStatsObserver observer) {
5750 mContext.enforceCallingOrSelfPermission(
5751 android.Manifest.permission.GET_PACKAGE_SIZE, null);
5752 // Queue up an async operation since the package deletion may take a little while.
5753 mHandler.post(new Runnable() {
5754 public void run() {
5755 mHandler.removeCallbacks(this);
5756 PackageStats lStats = new PackageStats(packageName);
5757 final boolean succeded;
5758 synchronized (mInstallLock) {
5759 succeded = getPackageSizeInfoLI(packageName, lStats);
5760 }
5761 if(observer != null) {
5762 try {
5763 observer.onGetStatsCompleted(lStats, succeded);
5764 } catch (RemoteException e) {
5765 Log.i(TAG, "Observer no longer exists.");
5766 }
5767 } //end if observer
5768 } //end run
5769 });
5770 }
5771
5772 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
5773 if (packageName == null) {
5774 Log.w(TAG, "Attempt to get size of null packageName.");
5775 return false;
5776 }
5777 PackageParser.Package p;
5778 boolean dataOnly = false;
5779 synchronized (mPackages) {
5780 p = mPackages.get(packageName);
5781 if(p == null) {
5782 dataOnly = true;
5783 PackageSetting ps = mSettings.mPackages.get(packageName);
5784 if((ps == null) || (ps.pkg == null)) {
5785 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5786 return false;
5787 }
5788 p = ps.pkg;
5789 }
5790 }
5791 String publicSrcDir = null;
5792 if(!dataOnly) {
5793 final ApplicationInfo applicationInfo = p.applicationInfo;
5794 if (applicationInfo == null) {
5795 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5796 return false;
5797 }
5798 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
5799 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005800 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 if (mInstaller != null) {
5802 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08005803 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005804 if (res < 0) {
5805 return false;
5806 } else {
5807 return true;
5808 }
5809 }
5810 return true;
5811 }
5812
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005814 public void addPackageToPreferred(String packageName) {
5815 mContext.enforceCallingOrSelfPermission(
5816 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005817 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 }
5819
5820 public void removePackageFromPreferred(String packageName) {
5821 mContext.enforceCallingOrSelfPermission(
5822 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005823 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005824 }
5825
5826 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005827 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 }
5829
5830 public void addPreferredActivity(IntentFilter filter, int match,
5831 ComponentName[] set, ComponentName activity) {
5832 mContext.enforceCallingOrSelfPermission(
5833 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5834
5835 synchronized (mPackages) {
5836 Log.i(TAG, "Adding preferred activity " + activity + ":");
5837 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5838 mSettings.mPreferredActivities.addFilter(
5839 new PreferredActivity(filter, match, set, activity));
5840 mSettings.writeLP();
5841 }
5842 }
5843
Satish Sampath8dbe6122009-06-02 23:35:54 +01005844 public void replacePreferredActivity(IntentFilter filter, int match,
5845 ComponentName[] set, ComponentName activity) {
5846 mContext.enforceCallingOrSelfPermission(
5847 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5848 if (filter.countActions() != 1) {
5849 throw new IllegalArgumentException(
5850 "replacePreferredActivity expects filter to have only 1 action.");
5851 }
5852 if (filter.countCategories() != 1) {
5853 throw new IllegalArgumentException(
5854 "replacePreferredActivity expects filter to have only 1 category.");
5855 }
5856 if (filter.countDataAuthorities() != 0
5857 || filter.countDataPaths() != 0
5858 || filter.countDataSchemes() != 0
5859 || filter.countDataTypes() != 0) {
5860 throw new IllegalArgumentException(
5861 "replacePreferredActivity expects filter to have no data authorities, " +
5862 "paths, schemes or types.");
5863 }
5864 synchronized (mPackages) {
5865 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5866 String action = filter.getAction(0);
5867 String category = filter.getCategory(0);
5868 while (it.hasNext()) {
5869 PreferredActivity pa = it.next();
5870 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5871 it.remove();
5872 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5873 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5874 }
5875 }
5876 addPreferredActivity(filter, match, set, activity);
5877 }
5878 }
5879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005880 public void clearPackagePreferredActivities(String packageName) {
5881 mContext.enforceCallingOrSelfPermission(
5882 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5883
5884 synchronized (mPackages) {
5885 if (clearPackagePreferredActivitiesLP(packageName)) {
5886 mSettings.writeLP();
5887 }
5888 }
5889 }
5890
5891 boolean clearPackagePreferredActivitiesLP(String packageName) {
5892 boolean changed = false;
5893 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5894 while (it.hasNext()) {
5895 PreferredActivity pa = it.next();
5896 if (pa.mActivity.getPackageName().equals(packageName)) {
5897 it.remove();
5898 changed = true;
5899 }
5900 }
5901 return changed;
5902 }
5903
5904 public int getPreferredActivities(List<IntentFilter> outFilters,
5905 List<ComponentName> outActivities, String packageName) {
5906
5907 int num = 0;
5908 synchronized (mPackages) {
5909 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5910 while (it.hasNext()) {
5911 PreferredActivity pa = it.next();
5912 if (packageName == null
5913 || pa.mActivity.getPackageName().equals(packageName)) {
5914 if (outFilters != null) {
5915 outFilters.add(new IntentFilter(pa));
5916 }
5917 if (outActivities != null) {
5918 outActivities.add(pa.mActivity);
5919 }
5920 }
5921 }
5922 }
5923
5924 return num;
5925 }
5926
5927 public void setApplicationEnabledSetting(String appPackageName,
5928 int newState, int flags) {
5929 setEnabledSetting(appPackageName, null, newState, flags);
5930 }
5931
5932 public void setComponentEnabledSetting(ComponentName componentName,
5933 int newState, int flags) {
5934 setEnabledSetting(componentName.getPackageName(),
5935 componentName.getClassName(), newState, flags);
5936 }
5937
5938 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005939 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5941 || newState == COMPONENT_ENABLED_STATE_ENABLED
5942 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5943 throw new IllegalArgumentException("Invalid new component state: "
5944 + newState);
5945 }
5946 PackageSetting pkgSetting;
5947 final int uid = Binder.getCallingUid();
5948 final int permission = mContext.checkCallingPermission(
5949 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5950 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005951 boolean sendNow = false;
5952 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005953 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005955 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005957 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005959 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005961 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 }
5963 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005964 "Unknown component: " + packageName
5965 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005966 }
5967 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5968 throw new SecurityException(
5969 "Permission Denial: attempt to change component state from pid="
5970 + Binder.getCallingPid()
5971 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5972 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005973 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005974 // We're dealing with an application/package level state change
5975 pkgSetting.enabled = newState;
5976 } else {
5977 // We're dealing with a component level state change
5978 switch (newState) {
5979 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005980 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005981 break;
5982 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005983 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 break;
5985 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005986 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 break;
5988 default:
5989 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005990 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 }
5992 }
5993 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005994 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005995 components = mPendingBroadcasts.get(packageName);
5996 boolean newPackage = components == null;
5997 if (newPackage) {
5998 components = new ArrayList<String>();
5999 }
6000 if (!components.contains(componentName)) {
6001 components.add(componentName);
6002 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006003 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6004 sendNow = true;
6005 // Purge entry from pending broadcast list if another one exists already
6006 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006007 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006008 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006009 if (newPackage) {
6010 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006011 }
6012 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6013 // Schedule a message
6014 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6015 }
6016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006017 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 long callingId = Binder.clearCallingIdentity();
6020 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006021 if (sendNow) {
6022 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006023 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006024 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 } finally {
6026 Binder.restoreCallingIdentity(callingId);
6027 }
6028 }
6029
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006030 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006031 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6032 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6033 + " components=" + componentNames);
6034 Bundle extras = new Bundle(4);
6035 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6036 String nameList[] = new String[componentNames.size()];
6037 componentNames.toArray(nameList);
6038 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006039 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
6040 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006041 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006042 }
6043
Jacek Surazski65e13172009-04-28 15:26:38 +02006044 public String getInstallerPackageName(String packageName) {
6045 synchronized (mPackages) {
6046 PackageSetting pkg = mSettings.mPackages.get(packageName);
6047 if (pkg == null) {
6048 throw new IllegalArgumentException("Unknown package: " + packageName);
6049 }
6050 return pkg.installerPackageName;
6051 }
6052 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 public int getApplicationEnabledSetting(String appPackageName) {
6055 synchronized (mPackages) {
6056 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
6057 if (pkg == null) {
6058 throw new IllegalArgumentException("Unknown package: " + appPackageName);
6059 }
6060 return pkg.enabled;
6061 }
6062 }
6063
6064 public int getComponentEnabledSetting(ComponentName componentName) {
6065 synchronized (mPackages) {
6066 final String packageNameStr = componentName.getPackageName();
6067 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
6068 if (pkg == null) {
6069 throw new IllegalArgumentException("Unknown component: " + componentName);
6070 }
6071 final String classNameStr = componentName.getClassName();
6072 return pkg.currentEnabledStateLP(classNameStr);
6073 }
6074 }
6075
6076 public void enterSafeMode() {
6077 if (!mSystemReady) {
6078 mSafeMode = true;
6079 }
6080 }
6081
6082 public void systemReady() {
6083 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006084
6085 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006086 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006087 mContext.getContentResolver(),
6088 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006089 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006090 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006091 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 }
6094
6095 public boolean isSafeMode() {
6096 return mSafeMode;
6097 }
6098
6099 public boolean hasSystemUidErrors() {
6100 return mHasSystemUidErrors;
6101 }
6102
6103 static String arrayToString(int[] array) {
6104 StringBuffer buf = new StringBuffer(128);
6105 buf.append('[');
6106 if (array != null) {
6107 for (int i=0; i<array.length; i++) {
6108 if (i > 0) buf.append(", ");
6109 buf.append(array[i]);
6110 }
6111 }
6112 buf.append(']');
6113 return buf.toString();
6114 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006116 @Override
6117 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6118 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6119 != PackageManager.PERMISSION_GRANTED) {
6120 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6121 + Binder.getCallingPid()
6122 + ", uid=" + Binder.getCallingUid()
6123 + " without permission "
6124 + android.Manifest.permission.DUMP);
6125 return;
6126 }
6127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006128 synchronized (mPackages) {
6129 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006130 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006131 pw.println(" ");
6132 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006133 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006134 pw.println(" ");
6135 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006136 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006137 pw.println(" ");
6138 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006139 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 pw.println("Permissions:");
6142 {
6143 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006144 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
6145 pw.print(Integer.toHexString(System.identityHashCode(p)));
6146 pw.println("):");
6147 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
6148 pw.print(" uid="); pw.print(p.uid);
6149 pw.print(" gids="); pw.print(arrayToString(p.gids));
6150 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 }
6152 }
6153 pw.println(" ");
6154 pw.println("Packages:");
6155 {
6156 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006157 pw.print(" Package [");
6158 pw.print(ps.realName != null ? ps.realName : ps.name);
6159 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006160 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6161 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006162 if (ps.realName != null) {
6163 pw.print(" compat name="); pw.println(ps.name);
6164 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006165 pw.print(" userId="); pw.print(ps.userId);
6166 pw.print(" gids="); pw.println(arrayToString(ps.gids));
6167 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6168 pw.print(" pkg="); pw.println(ps.pkg);
6169 pw.print(" codePath="); pw.println(ps.codePathString);
6170 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006172 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006173 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006174 pw.print(" supportsScreens=[");
6175 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006176 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006177 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006178 if (!first) pw.print(", ");
6179 first = false;
6180 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006181 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006182 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006183 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006184 if (!first) pw.print(", ");
6185 first = false;
6186 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006187 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006188 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006189 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006190 if (!first) pw.print(", ");
6191 first = false;
6192 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006193 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006194 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006195 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006196 if (!first) pw.print(", ");
6197 first = false;
6198 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006199 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006200 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006201 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
6202 if (!first) pw.print(", ");
6203 first = false;
6204 pw.print("anyDensity");
6205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006207 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006208 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
6209 pw.print(" signatures="); pw.println(ps.signatures);
6210 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
6211 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
6212 pw.print(" installStatus="); pw.print(ps.installStatus);
6213 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214 if (ps.disabledComponents.size() > 0) {
6215 pw.println(" disabledComponents:");
6216 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006217 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 }
6219 }
6220 if (ps.enabledComponents.size() > 0) {
6221 pw.println(" enabledComponents:");
6222 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006223 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 }
6225 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006226 if (ps.grantedPermissions.size() > 0) {
6227 pw.println(" grantedPermissions:");
6228 for (String s : ps.grantedPermissions) {
6229 pw.print(" "); pw.println(s);
6230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006231 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006232 if (ps.loadedPermissions.size() > 0) {
6233 pw.println(" loadedPermissions:");
6234 for (String s : ps.loadedPermissions) {
6235 pw.print(" "); pw.println(s);
6236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 }
6238 }
6239 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006240 if (mSettings.mRenamedPackages.size() > 0) {
6241 pw.println(" ");
6242 pw.println("Renamed packages:");
6243 for (HashMap.Entry<String, String> e
6244 : mSettings.mRenamedPackages.entrySet()) {
6245 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
6246 pw.println(e.getValue());
6247 }
6248 }
6249 if (mSettings.mDisabledSysPackages.size() > 0) {
6250 pw.println(" ");
6251 pw.println("Hidden system packages:");
6252 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
6253 pw.print(" Package [");
6254 pw.print(ps.realName != null ? ps.realName : ps.name);
6255 pw.print("] (");
6256 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6257 pw.println("):");
6258 if (ps.realName != null) {
6259 pw.print(" compat name="); pw.println(ps.name);
6260 }
6261 pw.print(" userId="); pw.println(ps.userId);
6262 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6263 pw.print(" codePath="); pw.println(ps.codePathString);
6264 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
6265 }
6266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 pw.println(" ");
6268 pw.println("Shared Users:");
6269 {
6270 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006271 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
6272 pw.print(Integer.toHexString(System.identityHashCode(su)));
6273 pw.println("):");
6274 pw.print(" userId="); pw.print(su.userId);
6275 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 pw.println(" grantedPermissions:");
6277 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006278 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 }
6280 pw.println(" loadedPermissions:");
6281 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006282 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006283 }
6284 }
6285 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 pw.println(" ");
6288 pw.println("Settings parse messages:");
6289 pw.println(mSettings.mReadMessages.toString());
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006290
6291 pw.println(" ");
6292 pw.println("Package warning messages:");
6293 File fname = getSettingsProblemFile();
6294 FileInputStream in;
6295 try {
6296 in = new FileInputStream(fname);
6297 int avail = in.available();
6298 byte[] data = new byte[avail];
6299 in.read(data);
6300 pw.println(new String(data));
6301 } catch (FileNotFoundException e) {
6302 } catch (IOException e) {
6303 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006305
6306 synchronized (mProviders) {
6307 pw.println(" ");
6308 pw.println("Registered ContentProviders:");
6309 for (PackageParser.Provider p : mProviders.values()) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006310 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006311 pw.println(p.toString());
6312 }
6313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 }
6315
6316 static final class BasePermission {
6317 final static int TYPE_NORMAL = 0;
6318 final static int TYPE_BUILTIN = 1;
6319 final static int TYPE_DYNAMIC = 2;
6320
6321 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006322 String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006323 final int type;
6324 PackageParser.Permission perm;
6325 PermissionInfo pendingInfo;
6326 int uid;
6327 int[] gids;
6328
6329 BasePermission(String _name, String _sourcePackage, int _type) {
6330 name = _name;
6331 sourcePackage = _sourcePackage;
6332 type = _type;
6333 }
6334 }
6335
6336 static class PackageSignatures {
6337 private Signature[] mSignatures;
6338
6339 PackageSignatures(Signature[] sigs) {
6340 assignSignatures(sigs);
6341 }
6342
6343 PackageSignatures() {
6344 }
6345
6346 void writeXml(XmlSerializer serializer, String tagName,
6347 ArrayList<Signature> pastSignatures) throws IOException {
6348 if (mSignatures == null) {
6349 return;
6350 }
6351 serializer.startTag(null, tagName);
6352 serializer.attribute(null, "count",
6353 Integer.toString(mSignatures.length));
6354 for (int i=0; i<mSignatures.length; i++) {
6355 serializer.startTag(null, "cert");
6356 final Signature sig = mSignatures[i];
6357 final int sigHash = sig.hashCode();
6358 final int numPast = pastSignatures.size();
6359 int j;
6360 for (j=0; j<numPast; j++) {
6361 Signature pastSig = pastSignatures.get(j);
6362 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
6363 serializer.attribute(null, "index", Integer.toString(j));
6364 break;
6365 }
6366 }
6367 if (j >= numPast) {
6368 pastSignatures.add(sig);
6369 serializer.attribute(null, "index", Integer.toString(numPast));
6370 serializer.attribute(null, "key", sig.toCharsString());
6371 }
6372 serializer.endTag(null, "cert");
6373 }
6374 serializer.endTag(null, tagName);
6375 }
6376
6377 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
6378 throws IOException, XmlPullParserException {
6379 String countStr = parser.getAttributeValue(null, "count");
6380 if (countStr == null) {
6381 reportSettingsProblem(Log.WARN,
6382 "Error in package manager settings: <signatures> has"
6383 + " no count at " + parser.getPositionDescription());
6384 XmlUtils.skipCurrentTag(parser);
6385 }
6386 final int count = Integer.parseInt(countStr);
6387 mSignatures = new Signature[count];
6388 int pos = 0;
6389
6390 int outerDepth = parser.getDepth();
6391 int type;
6392 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6393 && (type != XmlPullParser.END_TAG
6394 || parser.getDepth() > outerDepth)) {
6395 if (type == XmlPullParser.END_TAG
6396 || type == XmlPullParser.TEXT) {
6397 continue;
6398 }
6399
6400 String tagName = parser.getName();
6401 if (tagName.equals("cert")) {
6402 if (pos < count) {
6403 String index = parser.getAttributeValue(null, "index");
6404 if (index != null) {
6405 try {
6406 int idx = Integer.parseInt(index);
6407 String key = parser.getAttributeValue(null, "key");
6408 if (key == null) {
6409 if (idx >= 0 && idx < pastSignatures.size()) {
6410 Signature sig = pastSignatures.get(idx);
6411 if (sig != null) {
6412 mSignatures[pos] = pastSignatures.get(idx);
6413 pos++;
6414 } else {
6415 reportSettingsProblem(Log.WARN,
6416 "Error in package manager settings: <cert> "
6417 + "index " + index + " is not defined at "
6418 + parser.getPositionDescription());
6419 }
6420 } else {
6421 reportSettingsProblem(Log.WARN,
6422 "Error in package manager settings: <cert> "
6423 + "index " + index + " is out of bounds at "
6424 + parser.getPositionDescription());
6425 }
6426 } else {
6427 while (pastSignatures.size() <= idx) {
6428 pastSignatures.add(null);
6429 }
6430 Signature sig = new Signature(key);
6431 pastSignatures.set(idx, sig);
6432 mSignatures[pos] = sig;
6433 pos++;
6434 }
6435 } catch (NumberFormatException e) {
6436 reportSettingsProblem(Log.WARN,
6437 "Error in package manager settings: <cert> "
6438 + "index " + index + " is not a number at "
6439 + parser.getPositionDescription());
6440 }
6441 } else {
6442 reportSettingsProblem(Log.WARN,
6443 "Error in package manager settings: <cert> has"
6444 + " no index at " + parser.getPositionDescription());
6445 }
6446 } else {
6447 reportSettingsProblem(Log.WARN,
6448 "Error in package manager settings: too "
6449 + "many <cert> tags, expected " + count
6450 + " at " + parser.getPositionDescription());
6451 }
6452 } else {
6453 reportSettingsProblem(Log.WARN,
6454 "Unknown element under <cert>: "
6455 + parser.getName());
6456 }
6457 XmlUtils.skipCurrentTag(parser);
6458 }
6459
6460 if (pos < count) {
6461 // Should never happen -- there is an error in the written
6462 // settings -- but if it does we don't want to generate
6463 // a bad array.
6464 Signature[] newSigs = new Signature[pos];
6465 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
6466 mSignatures = newSigs;
6467 }
6468 }
6469
6470 /**
6471 * If any of the given 'sigs' is contained in the existing signatures,
6472 * then completely replace the current signatures with the ones in
6473 * 'sigs'. This is used for updating an existing package to a newly
6474 * installed version.
6475 */
6476 boolean updateSignatures(Signature[] sigs, boolean update) {
6477 if (mSignatures == null) {
6478 if (update) {
6479 assignSignatures(sigs);
6480 }
6481 return true;
6482 }
6483 if (sigs == null) {
6484 return false;
6485 }
6486
6487 for (int i=0; i<sigs.length; i++) {
6488 Signature sig = sigs[i];
6489 for (int j=0; j<mSignatures.length; j++) {
6490 if (mSignatures[j].equals(sig)) {
6491 if (update) {
6492 assignSignatures(sigs);
6493 }
6494 return true;
6495 }
6496 }
6497 }
6498 return false;
6499 }
6500
6501 /**
6502 * If any of the given 'sigs' is contained in the existing signatures,
6503 * then add in any new signatures found in 'sigs'. This is used for
6504 * including a new package into an existing shared user id.
6505 */
6506 boolean mergeSignatures(Signature[] sigs, boolean update) {
6507 if (mSignatures == null) {
6508 if (update) {
6509 assignSignatures(sigs);
6510 }
6511 return true;
6512 }
6513 if (sigs == null) {
6514 return false;
6515 }
6516
6517 Signature[] added = null;
6518 int addedCount = 0;
6519 boolean haveMatch = false;
6520 for (int i=0; i<sigs.length; i++) {
6521 Signature sig = sigs[i];
6522 boolean found = false;
6523 for (int j=0; j<mSignatures.length; j++) {
6524 if (mSignatures[j].equals(sig)) {
6525 found = true;
6526 haveMatch = true;
6527 break;
6528 }
6529 }
6530
6531 if (!found) {
6532 if (added == null) {
6533 added = new Signature[sigs.length];
6534 }
6535 added[i] = sig;
6536 addedCount++;
6537 }
6538 }
6539
6540 if (!haveMatch) {
6541 // Nothing matched -- reject the new signatures.
6542 return false;
6543 }
6544 if (added == null) {
6545 // Completely matched -- nothing else to do.
6546 return true;
6547 }
6548
6549 // Add additional signatures in.
6550 if (update) {
6551 Signature[] total = new Signature[addedCount+mSignatures.length];
6552 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6553 int j = mSignatures.length;
6554 for (int i=0; i<added.length; i++) {
6555 if (added[i] != null) {
6556 total[j] = added[i];
6557 j++;
6558 }
6559 }
6560 mSignatures = total;
6561 }
6562 return true;
6563 }
6564
6565 private void assignSignatures(Signature[] sigs) {
6566 if (sigs == null) {
6567 mSignatures = null;
6568 return;
6569 }
6570 mSignatures = new Signature[sigs.length];
6571 for (int i=0; i<sigs.length; i++) {
6572 mSignatures[i] = sigs[i];
6573 }
6574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 @Override
6577 public String toString() {
6578 StringBuffer buf = new StringBuffer(128);
6579 buf.append("PackageSignatures{");
6580 buf.append(Integer.toHexString(System.identityHashCode(this)));
6581 buf.append(" [");
6582 if (mSignatures != null) {
6583 for (int i=0; i<mSignatures.length; i++) {
6584 if (i > 0) buf.append(", ");
6585 buf.append(Integer.toHexString(
6586 System.identityHashCode(mSignatures[i])));
6587 }
6588 }
6589 buf.append("]}");
6590 return buf.toString();
6591 }
6592 }
6593
6594 static class PreferredActivity extends IntentFilter {
6595 final int mMatch;
6596 final String[] mSetPackages;
6597 final String[] mSetClasses;
6598 final String[] mSetComponents;
6599 final ComponentName mActivity;
6600 final String mShortActivity;
6601 String mParseError;
6602
6603 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6604 ComponentName activity) {
6605 super(filter);
6606 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6607 mActivity = activity;
6608 mShortActivity = activity.flattenToShortString();
6609 mParseError = null;
6610 if (set != null) {
6611 final int N = set.length;
6612 String[] myPackages = new String[N];
6613 String[] myClasses = new String[N];
6614 String[] myComponents = new String[N];
6615 for (int i=0; i<N; i++) {
6616 ComponentName cn = set[i];
6617 if (cn == null) {
6618 mSetPackages = null;
6619 mSetClasses = null;
6620 mSetComponents = null;
6621 return;
6622 }
6623 myPackages[i] = cn.getPackageName().intern();
6624 myClasses[i] = cn.getClassName().intern();
6625 myComponents[i] = cn.flattenToShortString().intern();
6626 }
6627 mSetPackages = myPackages;
6628 mSetClasses = myClasses;
6629 mSetComponents = myComponents;
6630 } else {
6631 mSetPackages = null;
6632 mSetClasses = null;
6633 mSetComponents = null;
6634 }
6635 }
6636
6637 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
6638 IOException {
6639 mShortActivity = parser.getAttributeValue(null, "name");
6640 mActivity = ComponentName.unflattenFromString(mShortActivity);
6641 if (mActivity == null) {
6642 mParseError = "Bad activity name " + mShortActivity;
6643 }
6644 String matchStr = parser.getAttributeValue(null, "match");
6645 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
6646 String setCountStr = parser.getAttributeValue(null, "set");
6647 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
6648
6649 String[] myPackages = setCount > 0 ? new String[setCount] : null;
6650 String[] myClasses = setCount > 0 ? new String[setCount] : null;
6651 String[] myComponents = setCount > 0 ? new String[setCount] : null;
6652
6653 int setPos = 0;
6654
6655 int outerDepth = parser.getDepth();
6656 int type;
6657 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6658 && (type != XmlPullParser.END_TAG
6659 || parser.getDepth() > outerDepth)) {
6660 if (type == XmlPullParser.END_TAG
6661 || type == XmlPullParser.TEXT) {
6662 continue;
6663 }
6664
6665 String tagName = parser.getName();
6666 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
6667 // + parser.getDepth() + " tag=" + tagName);
6668 if (tagName.equals("set")) {
6669 String name = parser.getAttributeValue(null, "name");
6670 if (name == null) {
6671 if (mParseError == null) {
6672 mParseError = "No name in set tag in preferred activity "
6673 + mShortActivity;
6674 }
6675 } else if (setPos >= setCount) {
6676 if (mParseError == null) {
6677 mParseError = "Too many set tags in preferred activity "
6678 + mShortActivity;
6679 }
6680 } else {
6681 ComponentName cn = ComponentName.unflattenFromString(name);
6682 if (cn == null) {
6683 if (mParseError == null) {
6684 mParseError = "Bad set name " + name + " in preferred activity "
6685 + mShortActivity;
6686 }
6687 } else {
6688 myPackages[setPos] = cn.getPackageName();
6689 myClasses[setPos] = cn.getClassName();
6690 myComponents[setPos] = name;
6691 setPos++;
6692 }
6693 }
6694 XmlUtils.skipCurrentTag(parser);
6695 } else if (tagName.equals("filter")) {
6696 //Log.i(TAG, "Starting to parse filter...");
6697 readFromXml(parser);
6698 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
6699 // + parser.getDepth() + " tag=" + parser.getName());
6700 } else {
6701 reportSettingsProblem(Log.WARN,
6702 "Unknown element under <preferred-activities>: "
6703 + parser.getName());
6704 XmlUtils.skipCurrentTag(parser);
6705 }
6706 }
6707
6708 if (setPos != setCount) {
6709 if (mParseError == null) {
6710 mParseError = "Not enough set tags (expected " + setCount
6711 + " but found " + setPos + ") in " + mShortActivity;
6712 }
6713 }
6714
6715 mSetPackages = myPackages;
6716 mSetClasses = myClasses;
6717 mSetComponents = myComponents;
6718 }
6719
6720 public void writeToXml(XmlSerializer serializer) throws IOException {
6721 final int NS = mSetClasses != null ? mSetClasses.length : 0;
6722 serializer.attribute(null, "name", mShortActivity);
6723 serializer.attribute(null, "match", Integer.toHexString(mMatch));
6724 serializer.attribute(null, "set", Integer.toString(NS));
6725 for (int s=0; s<NS; s++) {
6726 serializer.startTag(null, "set");
6727 serializer.attribute(null, "name", mSetComponents[s]);
6728 serializer.endTag(null, "set");
6729 }
6730 serializer.startTag(null, "filter");
6731 super.writeToXml(serializer);
6732 serializer.endTag(null, "filter");
6733 }
6734
6735 boolean sameSet(List<ResolveInfo> query, int priority) {
6736 if (mSetPackages == null) return false;
6737 final int NQ = query.size();
6738 final int NS = mSetPackages.length;
6739 int numMatch = 0;
6740 for (int i=0; i<NQ; i++) {
6741 ResolveInfo ri = query.get(i);
6742 if (ri.priority != priority) continue;
6743 ActivityInfo ai = ri.activityInfo;
6744 boolean good = false;
6745 for (int j=0; j<NS; j++) {
6746 if (mSetPackages[j].equals(ai.packageName)
6747 && mSetClasses[j].equals(ai.name)) {
6748 numMatch++;
6749 good = true;
6750 break;
6751 }
6752 }
6753 if (!good) return false;
6754 }
6755 return numMatch == NS;
6756 }
6757 }
6758
6759 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006760 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762 HashSet<String> grantedPermissions = new HashSet<String>();
6763 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006765 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006767 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08006768 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
6769 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
6770 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 }
6772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 /**
6775 * Settings base class for pending and resolved classes.
6776 */
6777 static class PackageSettingBase extends GrantedPermissions {
6778 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006779 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006780 File codePath;
6781 String codePathString;
6782 File resourcePath;
6783 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 private long timeStamp;
6785 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006786 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006788 boolean uidError;
6789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006790 PackageSignatures signatures = new PackageSignatures();
6791
6792 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006794 /* Explicitly disabled components */
6795 HashSet<String> disabledComponents = new HashSet<String>(0);
6796 /* Explicitly enabled components */
6797 HashSet<String> enabledComponents = new HashSet<String>(0);
6798 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6799 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006800
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006801 PackageSettingBase origPackage;
6802
Jacek Surazski65e13172009-04-28 15:26:38 +02006803 /* package name of the app that installed this package */
6804 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006806 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006807 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 super(pkgFlags);
6809 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006810 this.realName = realName;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006811 init(codePath, resourcePath, pVersionCode);
6812 }
6813
6814 void init(File codePath, File resourcePath, int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 this.codePath = codePath;
6816 this.codePathString = codePath.toString();
6817 this.resourcePath = resourcePath;
6818 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006819 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006820 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006821
Jacek Surazski65e13172009-04-28 15:26:38 +02006822 public void setInstallerPackageName(String packageName) {
6823 installerPackageName = packageName;
6824 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006825
Jacek Surazski65e13172009-04-28 15:26:38 +02006826 String getInstallerPackageName() {
6827 return installerPackageName;
6828 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006830 public void setInstallStatus(int newStatus) {
6831 installStatus = newStatus;
6832 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006834 public int getInstallStatus() {
6835 return installStatus;
6836 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006838 public void setTimeStamp(long newStamp) {
6839 if (newStamp != timeStamp) {
6840 timeStamp = newStamp;
6841 timeStampString = Long.toString(newStamp);
6842 }
6843 }
6844
6845 public void setTimeStamp(long newStamp, String newStampStr) {
6846 timeStamp = newStamp;
6847 timeStampString = newStampStr;
6848 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 public long getTimeStamp() {
6851 return timeStamp;
6852 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 public String getTimeStampStr() {
6855 return timeStampString;
6856 }
6857
6858 public void copyFrom(PackageSettingBase base) {
6859 grantedPermissions = base.grantedPermissions;
6860 gids = base.gids;
6861 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 timeStamp = base.timeStamp;
6864 timeStampString = base.timeStampString;
6865 signatures = base.signatures;
6866 permissionsFixed = base.permissionsFixed;
6867 disabledComponents = base.disabledComponents;
6868 enabledComponents = base.enabledComponents;
6869 enabled = base.enabled;
6870 installStatus = base.installStatus;
6871 }
6872
6873 void enableComponentLP(String componentClassName) {
6874 disabledComponents.remove(componentClassName);
6875 enabledComponents.add(componentClassName);
6876 }
6877
6878 void disableComponentLP(String componentClassName) {
6879 enabledComponents.remove(componentClassName);
6880 disabledComponents.add(componentClassName);
6881 }
6882
6883 void restoreComponentLP(String componentClassName) {
6884 enabledComponents.remove(componentClassName);
6885 disabledComponents.remove(componentClassName);
6886 }
6887
6888 int currentEnabledStateLP(String componentName) {
6889 if (enabledComponents.contains(componentName)) {
6890 return COMPONENT_ENABLED_STATE_ENABLED;
6891 } else if (disabledComponents.contains(componentName)) {
6892 return COMPONENT_ENABLED_STATE_DISABLED;
6893 } else {
6894 return COMPONENT_ENABLED_STATE_DEFAULT;
6895 }
6896 }
6897 }
6898
6899 /**
6900 * Settings data for a particular package we know about.
6901 */
6902 static final class PackageSetting extends PackageSettingBase {
6903 int userId;
6904 PackageParser.Package pkg;
6905 SharedUserSetting sharedUser;
6906
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006907 PackageSetting(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006908 int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006909 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912 @Override
6913 public String toString() {
6914 return "PackageSetting{"
6915 + Integer.toHexString(System.identityHashCode(this))
6916 + " " + name + "/" + userId + "}";
6917 }
6918 }
6919
6920 /**
6921 * Settings data for a particular shared user ID we know about.
6922 */
6923 static final class SharedUserSetting extends GrantedPermissions {
6924 final String name;
6925 int userId;
6926 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6927 final PackageSignatures signatures = new PackageSignatures();
6928
6929 SharedUserSetting(String _name, int _pkgFlags) {
6930 super(_pkgFlags);
6931 name = _name;
6932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 @Override
6935 public String toString() {
6936 return "SharedUserSetting{"
6937 + Integer.toHexString(System.identityHashCode(this))
6938 + " " + name + "/" + userId + "}";
6939 }
6940 }
6941
6942 /**
6943 * Holds information about dynamic settings.
6944 */
6945 private static final class Settings {
6946 private final File mSettingsFilename;
6947 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08006948 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 private final HashMap<String, PackageSetting> mPackages =
6950 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 // List of replaced system applications
6952 final HashMap<String, PackageSetting> mDisabledSysPackages =
6953 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006955 // The user's preferred activities associated with particular intent
6956 // filters.
6957 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6958 new IntentResolver<PreferredActivity, PreferredActivity>() {
6959 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006960 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006962 out.print(prefix); out.print(
6963 Integer.toHexString(System.identityHashCode(filter)));
6964 out.print(' ');
6965 out.print(filter.mActivity.flattenToShortString());
6966 out.print(" match=0x");
6967 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006969 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006971 out.print(prefix); out.print(" ");
6972 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 }
6974 }
6975 }
6976 };
6977 private final HashMap<String, SharedUserSetting> mSharedUsers =
6978 new HashMap<String, SharedUserSetting>();
6979 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6980 private final SparseArray<Object> mOtherUserIds =
6981 new SparseArray<Object>();
6982
6983 // For reading/writing settings file.
6984 private final ArrayList<Signature> mPastSignatures =
6985 new ArrayList<Signature>();
6986
6987 // Mapping from permission names to info about them.
6988 final HashMap<String, BasePermission> mPermissions =
6989 new HashMap<String, BasePermission>();
6990
6991 // Mapping from permission tree names to info about them.
6992 final HashMap<String, BasePermission> mPermissionTrees =
6993 new HashMap<String, BasePermission>();
6994
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006995 // Packages that have been uninstalled and still need their external
6996 // storage data deleted.
6997 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
6998
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006999 // Packages that have been renamed since they were first installed.
7000 // Keys are the new names of the packages, values are the original
7001 // names. The packages appear everwhere else under their original
7002 // names.
7003 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
7004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007005 private final StringBuilder mReadMessages = new StringBuilder();
7006
7007 private static final class PendingPackage extends PackageSettingBase {
7008 final int sharedId;
7009
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007010 PendingPackage(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007011 int sharedId, int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007012 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007013 this.sharedId = sharedId;
7014 }
7015 }
7016 private final ArrayList<PendingPackage> mPendingPackages
7017 = new ArrayList<PendingPackage>();
7018
7019 Settings() {
7020 File dataDir = Environment.getDataDirectory();
7021 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08007022 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
7023 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007025 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 FileUtils.setPermissions(systemDir.toString(),
7027 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7028 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7029 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08007030 FileUtils.setPermissions(systemSecureDir.toString(),
7031 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7032 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7033 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 mSettingsFilename = new File(systemDir, "packages.xml");
7035 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007036 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 }
7038
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007039 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007040 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 int pkgFlags, boolean create, boolean add) {
7042 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007043 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007044 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 return p;
7046 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007047
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007048 PackageSetting peekPackageLP(String name) {
7049 return mPackages.get(name);
7050 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 PackageSetting p = mPackages.get(name);
7052 if (p != null && p.codePath.getPath().equals(codePath)) {
7053 return p;
7054 }
7055 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007056 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 void setInstallStatus(String pkgName, int status) {
7060 PackageSetting p = mPackages.get(pkgName);
7061 if(p != null) {
7062 if(p.getInstallStatus() != status) {
7063 p.setInstallStatus(status);
7064 }
7065 }
7066 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007067
Jacek Surazski65e13172009-04-28 15:26:38 +02007068 void setInstallerPackageName(String pkgName,
7069 String installerPkgName) {
7070 PackageSetting p = mPackages.get(pkgName);
7071 if(p != null) {
7072 p.setInstallerPackageName(installerPkgName);
7073 }
7074 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007075
Jacek Surazski65e13172009-04-28 15:26:38 +02007076 String getInstallerPackageName(String pkgName) {
7077 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007078 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02007079 }
7080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 int getInstallStatus(String pkgName) {
7082 PackageSetting p = mPackages.get(pkgName);
7083 if(p != null) {
7084 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007086 return -1;
7087 }
7088
7089 SharedUserSetting getSharedUserLP(String name,
7090 int pkgFlags, boolean create) {
7091 SharedUserSetting s = mSharedUsers.get(name);
7092 if (s == null) {
7093 if (!create) {
7094 return null;
7095 }
7096 s = new SharedUserSetting(name, pkgFlags);
7097 if (MULTIPLE_APPLICATION_UIDS) {
7098 s.userId = newUserIdLP(s);
7099 } else {
7100 s.userId = FIRST_APPLICATION_UID;
7101 }
7102 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
7103 // < 0 means we couldn't assign a userid; fall out and return
7104 // s, which is currently null
7105 if (s.userId >= 0) {
7106 mSharedUsers.put(name, s);
7107 }
7108 }
7109
7110 return s;
7111 }
7112
7113 int disableSystemPackageLP(String name) {
7114 PackageSetting p = mPackages.get(name);
7115 if(p == null) {
7116 Log.w(TAG, "Package:"+name+" is not an installed package");
7117 return -1;
7118 }
7119 PackageSetting dp = mDisabledSysPackages.get(name);
7120 // always make sure the system package code and resource paths dont change
7121 if(dp == null) {
7122 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7123 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7124 }
7125 mDisabledSysPackages.put(name, p);
7126 }
7127 return removePackageLP(name);
7128 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 PackageSetting enableSystemPackageLP(String name) {
7131 PackageSetting p = mDisabledSysPackages.get(name);
7132 if(p == null) {
7133 Log.w(TAG, "Package:"+name+" is not disabled");
7134 return null;
7135 }
7136 // Reset flag in ApplicationInfo object
7137 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7138 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7139 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007140 PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007141 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 mDisabledSysPackages.remove(name);
7143 return ret;
7144 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007145
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007146 PackageSetting addPackageLP(String name, String realName, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007147 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 PackageSetting p = mPackages.get(name);
7149 if (p != null) {
7150 if (p.userId == uid) {
7151 return p;
7152 }
7153 reportSettingsProblem(Log.ERROR,
7154 "Adding duplicate package, keeping first: " + name);
7155 return null;
7156 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007157 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 p.userId = uid;
7159 if (addUserIdLP(uid, p, name)) {
7160 mPackages.put(name, p);
7161 return p;
7162 }
7163 return null;
7164 }
7165
7166 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
7167 SharedUserSetting s = mSharedUsers.get(name);
7168 if (s != null) {
7169 if (s.userId == uid) {
7170 return s;
7171 }
7172 reportSettingsProblem(Log.ERROR,
7173 "Adding duplicate shared user, keeping first: " + name);
7174 return null;
7175 }
7176 s = new SharedUserSetting(name, pkgFlags);
7177 s.userId = uid;
7178 if (addUserIdLP(uid, s, name)) {
7179 mSharedUsers.put(name, s);
7180 return s;
7181 }
7182 return null;
7183 }
7184
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007185 // Transfer ownership of permissions from one package to another.
7186 private void transferPermissions(String origPkg, String newPkg) {
7187 // Transfer ownership of permissions to the new package.
7188 for (int i=0; i<2; i++) {
7189 HashMap<String, BasePermission> permissions =
7190 i == 0 ? mPermissionTrees : mPermissions;
7191 for (BasePermission bp : permissions.values()) {
7192 if (origPkg.equals(bp.sourcePackage)) {
7193 if (DEBUG_UPGRADE) Log.v(TAG,
7194 "Moving permission " + bp.name
7195 + " from pkg " + bp.sourcePackage
7196 + " to " + newPkg);
7197 bp.sourcePackage = newPkg;
7198 bp.perm = null;
7199 if (bp.pendingInfo != null) {
7200 bp.sourcePackage = newPkg;
7201 }
7202 bp.uid = 0;
7203 bp.gids = null;
7204 }
7205 }
7206 }
7207 }
7208
7209 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007210 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007211 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007212 PackageSetting p = mPackages.get(name);
7213 if (p != null) {
7214 if (!p.codePath.equals(codePath)) {
7215 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007216 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007217 // This is an updated system app with versions in both system
7218 // and data partition. Just let the most recent version
7219 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007220 Log.w(TAG, "Trying to update system app code path from " +
7221 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007222 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007223 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07007224 reportSettingsProblem(Log.WARN,
7225 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007226 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007228 }
7229 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 reportSettingsProblem(Log.WARN,
7231 "Package " + name + " shared user changed from "
7232 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
7233 + " to "
7234 + (sharedUser != null ? sharedUser.name : "<nothing>")
7235 + "; replacing with new");
7236 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007237 } else {
7238 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7239 // If what we are scanning is a system package, then
7240 // make it so, regardless of whether it was previously
7241 // installed only in the data partition.
7242 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 }
7245 }
7246 if (p == null) {
7247 // Create a new PackageSettings entry. this can end up here because
7248 // of code path mismatch or user id mismatch of an updated system partition
7249 if (!create) {
7250 return null;
7251 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007252 if (origPackage != null) {
7253 // We are consuming the data from an existing package.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007254 p = new PackageSetting(origPackage.name, name, codePath,
7255 resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007256 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
7257 + " is adopting original package " + origPackage.name);
7258 p.copyFrom(origPackage);
7259 p.sharedUser = origPackage.sharedUser;
7260 p.userId = origPackage.userId;
7261 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007262 mRenamedPackages.put(name, origPackage.name);
7263 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007264 // Update new package state.
7265 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007267 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007268 p.setTimeStamp(codePath.lastModified());
7269 p.sharedUser = sharedUser;
7270 if (sharedUser != null) {
7271 p.userId = sharedUser.userId;
7272 } else if (MULTIPLE_APPLICATION_UIDS) {
7273 // Clone the setting here for disabled system packages
7274 PackageSetting dis = mDisabledSysPackages.get(name);
7275 if (dis != null) {
7276 // For disabled packages a new setting is created
7277 // from the existing user id. This still has to be
7278 // added to list of user id's
7279 // Copy signatures from previous setting
7280 if (dis.signatures.mSignatures != null) {
7281 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
7282 }
7283 p.userId = dis.userId;
7284 // Clone permissions
7285 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
7286 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
7287 // Clone component info
7288 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
7289 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
7290 // Add new setting to list of user ids
7291 addUserIdLP(p.userId, p, name);
7292 } else {
7293 // Assign new user id
7294 p.userId = newUserIdLP(p);
7295 }
7296 } else {
7297 p.userId = FIRST_APPLICATION_UID;
7298 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 }
7300 if (p.userId < 0) {
7301 reportSettingsProblem(Log.WARN,
7302 "Package " + name + " could not be assigned a valid uid");
7303 return null;
7304 }
7305 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007306 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007308 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007309 }
7310 }
7311 return p;
7312 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007313
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007314 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007315 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007316 String codePath = pkg.applicationInfo.sourceDir;
7317 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007318 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007319 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007320 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007321 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007322 p.codePath = new File(codePath);
7323 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007324 }
7325 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007326 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007327 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007328 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007329 p.resourcePath = new File(resourcePath);
7330 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007331 }
7332 // Update version code if needed
7333 if (pkg.mVersionCode != p.versionCode) {
7334 p.versionCode = pkg.mVersionCode;
7335 }
7336 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
7337 }
7338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 // Utility method that adds a PackageSetting to mPackages and
7340 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007341 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 SharedUserSetting sharedUser) {
7343 mPackages.put(name, p);
7344 if (sharedUser != null) {
7345 if (p.sharedUser != null && p.sharedUser != sharedUser) {
7346 reportSettingsProblem(Log.ERROR,
7347 "Package " + p.name + " was user "
7348 + p.sharedUser + " but is now " + sharedUser
7349 + "; I am not changing its files so it will probably fail!");
7350 p.sharedUser.packages.remove(p);
7351 } else if (p.userId != sharedUser.userId) {
7352 reportSettingsProblem(Log.ERROR,
7353 "Package " + p.name + " was user id " + p.userId
7354 + " but is now user " + sharedUser
7355 + " with id " + sharedUser.userId
7356 + "; I am not changing its files so it will probably fail!");
7357 }
7358
7359 sharedUser.packages.add(p);
7360 p.sharedUser = sharedUser;
7361 p.userId = sharedUser.userId;
7362 }
7363 }
7364
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007365 /*
7366 * Update the shared user setting when a package using
7367 * specifying the shared user id is removed. The gids
7368 * associated with each permission of the deleted package
7369 * are removed from the shared user's gid list only if its
7370 * not in use by other permissions of packages in the
7371 * shared user setting.
7372 */
7373 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
7375 Log.i(TAG, "Trying to update info for null package. Just ignoring");
7376 return;
7377 }
7378 // No sharedUserId
7379 if (deletedPs.sharedUser == null) {
7380 return;
7381 }
7382 SharedUserSetting sus = deletedPs.sharedUser;
7383 // Update permissions
7384 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
7385 boolean used = false;
7386 if (!sus.grantedPermissions.contains (eachPerm)) {
7387 continue;
7388 }
7389 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007390 if (pkg.pkg != null &&
7391 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
7392 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007393 used = true;
7394 break;
7395 }
7396 }
7397 if (!used) {
7398 // can safely delete this permission from list
7399 sus.grantedPermissions.remove(eachPerm);
7400 sus.loadedPermissions.remove(eachPerm);
7401 }
7402 }
7403 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007404 int newGids[] = globalGids;
7405 for (String eachPerm : sus.grantedPermissions) {
7406 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007407 if (bp != null) {
7408 newGids = appendInts(newGids, bp.gids);
7409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 }
7411 sus.gids = newGids;
7412 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 private int removePackageLP(String name) {
7415 PackageSetting p = mPackages.get(name);
7416 if (p != null) {
7417 mPackages.remove(name);
7418 if (p.sharedUser != null) {
7419 p.sharedUser.packages.remove(p);
7420 if (p.sharedUser.packages.size() == 0) {
7421 mSharedUsers.remove(p.sharedUser.name);
7422 removeUserIdLP(p.sharedUser.userId);
7423 return p.sharedUser.userId;
7424 }
7425 } else {
7426 removeUserIdLP(p.userId);
7427 return p.userId;
7428 }
7429 }
7430 return -1;
7431 }
7432
7433 private boolean addUserIdLP(int uid, Object obj, Object name) {
7434 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
7435 return false;
7436 }
7437
7438 if (uid >= FIRST_APPLICATION_UID) {
7439 int N = mUserIds.size();
7440 final int index = uid - FIRST_APPLICATION_UID;
7441 while (index >= N) {
7442 mUserIds.add(null);
7443 N++;
7444 }
7445 if (mUserIds.get(index) != null) {
7446 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007447 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007448 + " name=" + name);
7449 return false;
7450 }
7451 mUserIds.set(index, obj);
7452 } else {
7453 if (mOtherUserIds.get(uid) != null) {
7454 reportSettingsProblem(Log.ERROR,
7455 "Adding duplicate shared id: " + uid
7456 + " name=" + name);
7457 return false;
7458 }
7459 mOtherUserIds.put(uid, obj);
7460 }
7461 return true;
7462 }
7463
7464 public Object getUserIdLP(int uid) {
7465 if (uid >= FIRST_APPLICATION_UID) {
7466 int N = mUserIds.size();
7467 final int index = uid - FIRST_APPLICATION_UID;
7468 return index < N ? mUserIds.get(index) : null;
7469 } else {
7470 return mOtherUserIds.get(uid);
7471 }
7472 }
7473
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007474 private Set<String> findPackagesWithFlag(int flag) {
7475 Set<String> ret = new HashSet<String>();
7476 for (PackageSetting ps : mPackages.values()) {
7477 // Has to match atleast all the flag bits set on flag
7478 if ((ps.pkgFlags & flag) == flag) {
7479 ret.add(ps.name);
7480 }
7481 }
7482 return ret;
7483 }
7484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 private void removeUserIdLP(int uid) {
7486 if (uid >= FIRST_APPLICATION_UID) {
7487 int N = mUserIds.size();
7488 final int index = uid - FIRST_APPLICATION_UID;
7489 if (index < N) mUserIds.set(index, null);
7490 } else {
7491 mOtherUserIds.remove(uid);
7492 }
7493 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 void writeLP() {
7496 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
7497
7498 // Keep the old settings around until we know the new ones have
7499 // been successfully written.
7500 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007501 // Presence of backup settings file indicates that we failed
7502 // to persist settings earlier. So preserve the older
7503 // backup for future reference since the current settings
7504 // might have been corrupted.
7505 if (!mBackupSettingsFilename.exists()) {
7506 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
7507 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
7508 return;
7509 }
7510 } else {
7511 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07007512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 }
7514
7515 mPastSignatures.clear();
7516
7517 try {
7518 FileOutputStream str = new FileOutputStream(mSettingsFilename);
7519
7520 //XmlSerializer serializer = XmlUtils.serializerInstance();
7521 XmlSerializer serializer = new FastXmlSerializer();
7522 serializer.setOutput(str, "utf-8");
7523 serializer.startDocument(null, true);
7524 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
7525
7526 serializer.startTag(null, "packages");
7527
7528 serializer.startTag(null, "permission-trees");
7529 for (BasePermission bp : mPermissionTrees.values()) {
7530 writePermission(serializer, bp);
7531 }
7532 serializer.endTag(null, "permission-trees");
7533
7534 serializer.startTag(null, "permissions");
7535 for (BasePermission bp : mPermissions.values()) {
7536 writePermission(serializer, bp);
7537 }
7538 serializer.endTag(null, "permissions");
7539
7540 for (PackageSetting pkg : mPackages.values()) {
7541 writePackage(serializer, pkg);
7542 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007544 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7545 writeDisabledSysPackage(serializer, pkg);
7546 }
7547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 serializer.startTag(null, "preferred-activities");
7549 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7550 serializer.startTag(null, "item");
7551 pa.writeToXml(serializer);
7552 serializer.endTag(null, "item");
7553 }
7554 serializer.endTag(null, "preferred-activities");
7555
7556 for (SharedUserSetting usr : mSharedUsers.values()) {
7557 serializer.startTag(null, "shared-user");
7558 serializer.attribute(null, "name", usr.name);
7559 serializer.attribute(null, "userId",
7560 Integer.toString(usr.userId));
7561 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7562 serializer.startTag(null, "perms");
7563 for (String name : usr.grantedPermissions) {
7564 serializer.startTag(null, "item");
7565 serializer.attribute(null, "name", name);
7566 serializer.endTag(null, "item");
7567 }
7568 serializer.endTag(null, "perms");
7569 serializer.endTag(null, "shared-user");
7570 }
7571
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007572 if (mPackagesToBeCleaned.size() > 0) {
7573 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
7574 serializer.startTag(null, "cleaning-package");
7575 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
7576 serializer.endTag(null, "cleaning-package");
7577 }
7578 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007579
7580 if (mRenamedPackages.size() > 0) {
7581 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
7582 serializer.startTag(null, "renamed-package");
7583 serializer.attribute(null, "new", e.getKey());
7584 serializer.attribute(null, "old", e.getValue());
7585 serializer.endTag(null, "renamed-package");
7586 }
7587 }
7588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 serializer.endTag(null, "packages");
7590
7591 serializer.endDocument();
7592
7593 str.flush();
7594 str.close();
7595
7596 // New settings successfully written, old ones are no longer
7597 // needed.
7598 mBackupSettingsFilename.delete();
7599 FileUtils.setPermissions(mSettingsFilename.toString(),
7600 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7601 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7602 |FileUtils.S_IROTH,
7603 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007604
7605 // Write package list file now, use a JournaledFile.
7606 //
7607 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
7608 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
7609
7610 str = new FileOutputStream(journal.chooseForWrite());
7611 try {
7612 StringBuilder sb = new StringBuilder();
7613 for (PackageSetting pkg : mPackages.values()) {
7614 ApplicationInfo ai = pkg.pkg.applicationInfo;
7615 String dataPath = ai.dataDir;
7616 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
7617
7618 // Avoid any application that has a space in its path
7619 // or that is handled by the system.
7620 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
7621 continue;
7622
7623 // we store on each line the following information for now:
7624 //
7625 // pkgName - package name
7626 // userId - application-specific user id
7627 // debugFlag - 0 or 1 if the package is debuggable.
7628 // dataPath - path to package's data path
7629 //
7630 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
7631 //
7632 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
7633 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
7634 // system/core/run-as/run-as.c
7635 //
7636 sb.setLength(0);
7637 sb.append(ai.packageName);
7638 sb.append(" ");
7639 sb.append((int)ai.uid);
7640 sb.append(isDebug ? " 1 " : " 0 ");
7641 sb.append(dataPath);
7642 sb.append("\n");
7643 str.write(sb.toString().getBytes());
7644 }
7645 str.flush();
7646 str.close();
7647 journal.commit();
7648 }
7649 catch (Exception e) {
7650 journal.rollback();
7651 }
7652
7653 FileUtils.setPermissions(mPackageListFilename.toString(),
7654 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7655 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7656 |FileUtils.S_IROTH,
7657 -1, -1);
7658
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007659 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007660
7661 } catch(XmlPullParserException e) {
7662 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 -08007663 } catch(java.io.IOException e) {
7664 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 -08007665 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007666 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007667 if (mSettingsFilename.exists()) {
7668 if (!mSettingsFilename.delete()) {
7669 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
7670 }
7671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007672 //Debug.stopMethodTracing();
7673 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007674
7675 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007676 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 serializer.startTag(null, "updated-package");
7678 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007679 if (pkg.realName != null) {
7680 serializer.attribute(null, "realName", pkg.realName);
7681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007682 serializer.attribute(null, "codePath", pkg.codePathString);
7683 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007684 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007685 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7686 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7687 }
7688 if (pkg.sharedUser == null) {
7689 serializer.attribute(null, "userId",
7690 Integer.toString(pkg.userId));
7691 } else {
7692 serializer.attribute(null, "sharedUserId",
7693 Integer.toString(pkg.userId));
7694 }
7695 serializer.startTag(null, "perms");
7696 if (pkg.sharedUser == null) {
7697 // If this is a shared user, the permissions will
7698 // be written there. We still need to write an
7699 // empty permissions list so permissionsFixed will
7700 // be set.
7701 for (final String name : pkg.grantedPermissions) {
7702 BasePermission bp = mPermissions.get(name);
7703 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
7704 // We only need to write signature or system permissions but this wont
7705 // match the semantics of grantedPermissions. So write all permissions.
7706 serializer.startTag(null, "item");
7707 serializer.attribute(null, "name", name);
7708 serializer.endTag(null, "item");
7709 }
7710 }
7711 }
7712 serializer.endTag(null, "perms");
7713 serializer.endTag(null, "updated-package");
7714 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007715
7716 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007717 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007718 serializer.startTag(null, "package");
7719 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007720 if (pkg.realName != null) {
7721 serializer.attribute(null, "realName", pkg.realName);
7722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007723 serializer.attribute(null, "codePath", pkg.codePathString);
7724 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7725 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7726 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007727 serializer.attribute(null, "flags",
7728 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007730 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007731 if (pkg.sharedUser == null) {
7732 serializer.attribute(null, "userId",
7733 Integer.toString(pkg.userId));
7734 } else {
7735 serializer.attribute(null, "sharedUserId",
7736 Integer.toString(pkg.userId));
7737 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007738 if (pkg.uidError) {
7739 serializer.attribute(null, "uidError", "true");
7740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
7742 serializer.attribute(null, "enabled",
7743 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
7744 ? "true" : "false");
7745 }
7746 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
7747 serializer.attribute(null, "installStatus", "false");
7748 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007749 if (pkg.installerPackageName != null) {
7750 serializer.attribute(null, "installer", pkg.installerPackageName);
7751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007752 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
7753 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
7754 serializer.startTag(null, "perms");
7755 if (pkg.sharedUser == null) {
7756 // If this is a shared user, the permissions will
7757 // be written there. We still need to write an
7758 // empty permissions list so permissionsFixed will
7759 // be set.
7760 for (final String name : pkg.grantedPermissions) {
7761 serializer.startTag(null, "item");
7762 serializer.attribute(null, "name", name);
7763 serializer.endTag(null, "item");
7764 }
7765 }
7766 serializer.endTag(null, "perms");
7767 }
7768 if (pkg.disabledComponents.size() > 0) {
7769 serializer.startTag(null, "disabled-components");
7770 for (final String name : pkg.disabledComponents) {
7771 serializer.startTag(null, "item");
7772 serializer.attribute(null, "name", name);
7773 serializer.endTag(null, "item");
7774 }
7775 serializer.endTag(null, "disabled-components");
7776 }
7777 if (pkg.enabledComponents.size() > 0) {
7778 serializer.startTag(null, "enabled-components");
7779 for (final String name : pkg.enabledComponents) {
7780 serializer.startTag(null, "item");
7781 serializer.attribute(null, "name", name);
7782 serializer.endTag(null, "item");
7783 }
7784 serializer.endTag(null, "enabled-components");
7785 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 serializer.endTag(null, "package");
7788 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 void writePermission(XmlSerializer serializer, BasePermission bp)
7791 throws XmlPullParserException, java.io.IOException {
7792 if (bp.type != BasePermission.TYPE_BUILTIN
7793 && bp.sourcePackage != null) {
7794 serializer.startTag(null, "item");
7795 serializer.attribute(null, "name", bp.name);
7796 serializer.attribute(null, "package", bp.sourcePackage);
7797 if (DEBUG_SETTINGS) Log.v(TAG,
7798 "Writing perm: name=" + bp.name + " type=" + bp.type);
7799 if (bp.type == BasePermission.TYPE_DYNAMIC) {
7800 PermissionInfo pi = bp.perm != null ? bp.perm.info
7801 : bp.pendingInfo;
7802 if (pi != null) {
7803 serializer.attribute(null, "type", "dynamic");
7804 if (pi.icon != 0) {
7805 serializer.attribute(null, "icon",
7806 Integer.toString(pi.icon));
7807 }
7808 if (pi.nonLocalizedLabel != null) {
7809 serializer.attribute(null, "label",
7810 pi.nonLocalizedLabel.toString());
7811 }
7812 if (pi.protectionLevel !=
7813 PermissionInfo.PROTECTION_NORMAL) {
7814 serializer.attribute(null, "protection",
7815 Integer.toString(pi.protectionLevel));
7816 }
7817 }
7818 }
7819 serializer.endTag(null, "item");
7820 }
7821 }
7822
7823 String getReadMessagesLP() {
7824 return mReadMessages.toString();
7825 }
7826
Oscar Montemayora8529f62009-11-18 10:14:20 -08007827 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007828 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
7829 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007830 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 while(its.hasNext()) {
7832 String key = its.next();
7833 PackageSetting ps = mPackages.get(key);
7834 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08007835 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007836 }
7837 }
7838 return ret;
7839 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 boolean readLP() {
7842 FileInputStream str = null;
7843 if (mBackupSettingsFilename.exists()) {
7844 try {
7845 str = new FileInputStream(mBackupSettingsFilename);
7846 mReadMessages.append("Reading from backup settings file\n");
7847 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007848 if (mSettingsFilename.exists()) {
7849 // If both the backup and settings file exist, we
7850 // ignore the settings since it might have been
7851 // corrupted.
7852 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
7853 mSettingsFilename.delete();
7854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007855 } catch (java.io.IOException e) {
7856 // We'll try for the normal settings file.
7857 }
7858 }
7859
7860 mPastSignatures.clear();
7861
7862 try {
7863 if (str == null) {
7864 if (!mSettingsFilename.exists()) {
7865 mReadMessages.append("No settings file found\n");
7866 Log.i(TAG, "No current settings file!");
7867 return false;
7868 }
7869 str = new FileInputStream(mSettingsFilename);
7870 }
7871 XmlPullParser parser = Xml.newPullParser();
7872 parser.setInput(str, null);
7873
7874 int type;
7875 while ((type=parser.next()) != XmlPullParser.START_TAG
7876 && type != XmlPullParser.END_DOCUMENT) {
7877 ;
7878 }
7879
7880 if (type != XmlPullParser.START_TAG) {
7881 mReadMessages.append("No start tag found in settings file\n");
7882 Log.e(TAG, "No start tag found in package manager settings");
7883 return false;
7884 }
7885
7886 int outerDepth = parser.getDepth();
7887 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7888 && (type != XmlPullParser.END_TAG
7889 || parser.getDepth() > outerDepth)) {
7890 if (type == XmlPullParser.END_TAG
7891 || type == XmlPullParser.TEXT) {
7892 continue;
7893 }
7894
7895 String tagName = parser.getName();
7896 if (tagName.equals("package")) {
7897 readPackageLP(parser);
7898 } else if (tagName.equals("permissions")) {
7899 readPermissionsLP(mPermissions, parser);
7900 } else if (tagName.equals("permission-trees")) {
7901 readPermissionsLP(mPermissionTrees, parser);
7902 } else if (tagName.equals("shared-user")) {
7903 readSharedUserLP(parser);
7904 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007905 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 } else if (tagName.equals("preferred-activities")) {
7907 readPreferredActivitiesLP(parser);
7908 } else if(tagName.equals("updated-package")) {
7909 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007910 } else if (tagName.equals("cleaning-package")) {
7911 String name = parser.getAttributeValue(null, "name");
7912 if (name != null) {
7913 mPackagesToBeCleaned.add(name);
7914 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007915 } else if (tagName.equals("renamed-package")) {
7916 String nname = parser.getAttributeValue(null, "new");
7917 String oname = parser.getAttributeValue(null, "old");
7918 if (nname != null && oname != null) {
7919 mRenamedPackages.put(nname, oname);
7920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007921 } else {
7922 Log.w(TAG, "Unknown element under <packages>: "
7923 + parser.getName());
7924 XmlUtils.skipCurrentTag(parser);
7925 }
7926 }
7927
7928 str.close();
7929
7930 } catch(XmlPullParserException e) {
7931 mReadMessages.append("Error reading: " + e.toString());
7932 Log.e(TAG, "Error reading package manager settings", e);
7933
7934 } catch(java.io.IOException e) {
7935 mReadMessages.append("Error reading: " + e.toString());
7936 Log.e(TAG, "Error reading package manager settings", e);
7937
7938 }
7939
7940 int N = mPendingPackages.size();
7941 for (int i=0; i<N; i++) {
7942 final PendingPackage pp = mPendingPackages.get(i);
7943 Object idObj = getUserIdLP(pp.sharedId);
7944 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007945 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007947 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 if (p == null) {
7949 Log.w(TAG, "Unable to create application package for "
7950 + pp.name);
7951 continue;
7952 }
7953 p.copyFrom(pp);
7954 } else if (idObj != null) {
7955 String msg = "Bad package setting: package " + pp.name
7956 + " has shared uid " + pp.sharedId
7957 + " that is not a shared uid\n";
7958 mReadMessages.append(msg);
7959 Log.e(TAG, msg);
7960 } else {
7961 String msg = "Bad package setting: package " + pp.name
7962 + " has shared uid " + pp.sharedId
7963 + " that is not defined\n";
7964 mReadMessages.append(msg);
7965 Log.e(TAG, msg);
7966 }
7967 }
7968 mPendingPackages.clear();
7969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 mReadMessages.append("Read completed successfully: "
7971 + mPackages.size() + " packages, "
7972 + mSharedUsers.size() + " shared uids\n");
7973
7974 return true;
7975 }
7976
7977 private int readInt(XmlPullParser parser, String ns, String name,
7978 int defValue) {
7979 String v = parser.getAttributeValue(ns, name);
7980 try {
7981 if (v == null) {
7982 return defValue;
7983 }
7984 return Integer.parseInt(v);
7985 } catch (NumberFormatException e) {
7986 reportSettingsProblem(Log.WARN,
7987 "Error in package manager settings: attribute " +
7988 name + " has bad integer value " + v + " at "
7989 + parser.getPositionDescription());
7990 }
7991 return defValue;
7992 }
7993
7994 private void readPermissionsLP(HashMap<String, BasePermission> out,
7995 XmlPullParser parser)
7996 throws IOException, XmlPullParserException {
7997 int outerDepth = parser.getDepth();
7998 int type;
7999 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8000 && (type != XmlPullParser.END_TAG
8001 || parser.getDepth() > outerDepth)) {
8002 if (type == XmlPullParser.END_TAG
8003 || type == XmlPullParser.TEXT) {
8004 continue;
8005 }
8006
8007 String tagName = parser.getName();
8008 if (tagName.equals("item")) {
8009 String name = parser.getAttributeValue(null, "name");
8010 String sourcePackage = parser.getAttributeValue(null, "package");
8011 String ptype = parser.getAttributeValue(null, "type");
8012 if (name != null && sourcePackage != null) {
8013 boolean dynamic = "dynamic".equals(ptype);
8014 BasePermission bp = new BasePermission(name, sourcePackage,
8015 dynamic
8016 ? BasePermission.TYPE_DYNAMIC
8017 : BasePermission.TYPE_NORMAL);
8018 if (dynamic) {
8019 PermissionInfo pi = new PermissionInfo();
8020 pi.packageName = sourcePackage.intern();
8021 pi.name = name.intern();
8022 pi.icon = readInt(parser, null, "icon", 0);
8023 pi.nonLocalizedLabel = parser.getAttributeValue(
8024 null, "label");
8025 pi.protectionLevel = readInt(parser, null, "protection",
8026 PermissionInfo.PROTECTION_NORMAL);
8027 bp.pendingInfo = pi;
8028 }
8029 out.put(bp.name, bp);
8030 } else {
8031 reportSettingsProblem(Log.WARN,
8032 "Error in package manager settings: permissions has"
8033 + " no name at " + parser.getPositionDescription());
8034 }
8035 } else {
8036 reportSettingsProblem(Log.WARN,
8037 "Unknown element reading permissions: "
8038 + parser.getName() + " at "
8039 + parser.getPositionDescription());
8040 }
8041 XmlUtils.skipCurrentTag(parser);
8042 }
8043 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008046 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008047 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008048 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008049 String codePathStr = parser.getAttributeValue(null, "codePath");
8050 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008051 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 resourcePathStr = codePathStr;
8053 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008054 String version = parser.getAttributeValue(null, "version");
8055 int versionCode = 0;
8056 if (version != null) {
8057 try {
8058 versionCode = Integer.parseInt(version);
8059 } catch (NumberFormatException e) {
8060 }
8061 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 int pkgFlags = 0;
8064 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008065 PackageSetting ps = new PackageSetting(name, realName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008066 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008067 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 String timeStampStr = parser.getAttributeValue(null, "ts");
8069 if (timeStampStr != null) {
8070 try {
8071 long timeStamp = Long.parseLong(timeStampStr);
8072 ps.setTimeStamp(timeStamp, timeStampStr);
8073 } catch (NumberFormatException e) {
8074 }
8075 }
8076 String idStr = parser.getAttributeValue(null, "userId");
8077 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
8078 if(ps.userId <= 0) {
8079 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8080 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
8081 }
8082 int outerDepth = parser.getDepth();
8083 int type;
8084 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8085 && (type != XmlPullParser.END_TAG
8086 || parser.getDepth() > outerDepth)) {
8087 if (type == XmlPullParser.END_TAG
8088 || type == XmlPullParser.TEXT) {
8089 continue;
8090 }
8091
8092 String tagName = parser.getName();
8093 if (tagName.equals("perms")) {
8094 readGrantedPermissionsLP(parser,
8095 ps.grantedPermissions);
8096 } else {
8097 reportSettingsProblem(Log.WARN,
8098 "Unknown element under <updated-package>: "
8099 + parser.getName());
8100 XmlUtils.skipCurrentTag(parser);
8101 }
8102 }
8103 mDisabledSysPackages.put(name, ps);
8104 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008106 private void readPackageLP(XmlPullParser parser)
8107 throws XmlPullParserException, IOException {
8108 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008109 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008110 String idStr = null;
8111 String sharedIdStr = null;
8112 String codePathStr = null;
8113 String resourcePathStr = null;
8114 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02008115 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008116 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 int pkgFlags = 0;
8118 String timeStampStr;
8119 long timeStamp = 0;
8120 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008121 String version = null;
8122 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008123 try {
8124 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008125 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008126 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008127 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8129 codePathStr = parser.getAttributeValue(null, "codePath");
8130 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008131 version = parser.getAttributeValue(null, "version");
8132 if (version != null) {
8133 try {
8134 versionCode = Integer.parseInt(version);
8135 } catch (NumberFormatException e) {
8136 }
8137 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008138 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008139
8140 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008141 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008142 try {
8143 pkgFlags = Integer.parseInt(systemStr);
8144 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 }
8146 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008147 // For backward compatibility
8148 systemStr = parser.getAttributeValue(null, "system");
8149 if (systemStr != null) {
8150 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
8151 } else {
8152 // Old settings that don't specify system... just treat
8153 // them as system, good enough.
8154 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008156 }
8157 timeStampStr = parser.getAttributeValue(null, "ts");
8158 if (timeStampStr != null) {
8159 try {
8160 timeStamp = Long.parseLong(timeStampStr);
8161 } catch (NumberFormatException e) {
8162 }
8163 }
8164 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
8165 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
8166 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8167 if (resourcePathStr == null) {
8168 resourcePathStr = codePathStr;
8169 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008170 if (realName != null) {
8171 realName = realName.intern();
8172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 if (name == null) {
8174 reportSettingsProblem(Log.WARN,
8175 "Error in package manager settings: <package> has no name at "
8176 + parser.getPositionDescription());
8177 } else if (codePathStr == null) {
8178 reportSettingsProblem(Log.WARN,
8179 "Error in package manager settings: <package> has no codePath at "
8180 + parser.getPositionDescription());
8181 } else if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008182 packageSetting = addPackageLP(name.intern(), realName,
8183 new File(codePathStr), new File(resourcePathStr),
8184 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8186 + ": userId=" + userId + " pkg=" + packageSetting);
8187 if (packageSetting == null) {
8188 reportSettingsProblem(Log.ERROR,
8189 "Failure adding uid " + userId
8190 + " while parsing settings at "
8191 + parser.getPositionDescription());
8192 } else {
8193 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8194 }
8195 } else if (sharedIdStr != null) {
8196 userId = sharedIdStr != null
8197 ? Integer.parseInt(sharedIdStr) : 0;
8198 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008199 packageSetting = new PendingPackage(name.intern(), realName,
8200 new File(codePathStr), new File(resourcePathStr),
8201 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8203 mPendingPackages.add((PendingPackage) packageSetting);
8204 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8205 + ": sharedUserId=" + userId + " pkg="
8206 + packageSetting);
8207 } else {
8208 reportSettingsProblem(Log.WARN,
8209 "Error in package manager settings: package "
8210 + name + " has bad sharedId " + sharedIdStr
8211 + " at " + parser.getPositionDescription());
8212 }
8213 } else {
8214 reportSettingsProblem(Log.WARN,
8215 "Error in package manager settings: package "
8216 + name + " has bad userId " + idStr + " at "
8217 + parser.getPositionDescription());
8218 }
8219 } catch (NumberFormatException e) {
8220 reportSettingsProblem(Log.WARN,
8221 "Error in package manager settings: package "
8222 + name + " has bad userId " + idStr + " at "
8223 + parser.getPositionDescription());
8224 }
8225 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008226 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02008227 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 final String enabledStr = parser.getAttributeValue(null, "enabled");
8229 if (enabledStr != null) {
8230 if (enabledStr.equalsIgnoreCase("true")) {
8231 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
8232 } else if (enabledStr.equalsIgnoreCase("false")) {
8233 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
8234 } else if (enabledStr.equalsIgnoreCase("default")) {
8235 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8236 } else {
8237 reportSettingsProblem(Log.WARN,
8238 "Error in package manager settings: package "
8239 + name + " has bad enabled value: " + idStr
8240 + " at " + parser.getPositionDescription());
8241 }
8242 } else {
8243 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8244 }
8245 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
8246 if (installStatusStr != null) {
8247 if (installStatusStr.equalsIgnoreCase("false")) {
8248 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
8249 } else {
8250 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
8251 }
8252 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 int outerDepth = parser.getDepth();
8255 int type;
8256 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8257 && (type != XmlPullParser.END_TAG
8258 || parser.getDepth() > outerDepth)) {
8259 if (type == XmlPullParser.END_TAG
8260 || type == XmlPullParser.TEXT) {
8261 continue;
8262 }
8263
8264 String tagName = parser.getName();
8265 if (tagName.equals("disabled-components")) {
8266 readDisabledComponentsLP(packageSetting, parser);
8267 } else if (tagName.equals("enabled-components")) {
8268 readEnabledComponentsLP(packageSetting, parser);
8269 } else if (tagName.equals("sigs")) {
8270 packageSetting.signatures.readXml(parser, mPastSignatures);
8271 } else if (tagName.equals("perms")) {
8272 readGrantedPermissionsLP(parser,
8273 packageSetting.loadedPermissions);
8274 packageSetting.permissionsFixed = true;
8275 } else {
8276 reportSettingsProblem(Log.WARN,
8277 "Unknown element under <package>: "
8278 + parser.getName());
8279 XmlUtils.skipCurrentTag(parser);
8280 }
8281 }
8282 } else {
8283 XmlUtils.skipCurrentTag(parser);
8284 }
8285 }
8286
8287 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
8288 XmlPullParser parser)
8289 throws IOException, XmlPullParserException {
8290 int outerDepth = parser.getDepth();
8291 int type;
8292 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8293 && (type != XmlPullParser.END_TAG
8294 || parser.getDepth() > outerDepth)) {
8295 if (type == XmlPullParser.END_TAG
8296 || type == XmlPullParser.TEXT) {
8297 continue;
8298 }
8299
8300 String tagName = parser.getName();
8301 if (tagName.equals("item")) {
8302 String name = parser.getAttributeValue(null, "name");
8303 if (name != null) {
8304 packageSetting.disabledComponents.add(name.intern());
8305 } else {
8306 reportSettingsProblem(Log.WARN,
8307 "Error in package manager settings: <disabled-components> has"
8308 + " no name at " + parser.getPositionDescription());
8309 }
8310 } else {
8311 reportSettingsProblem(Log.WARN,
8312 "Unknown element under <disabled-components>: "
8313 + parser.getName());
8314 }
8315 XmlUtils.skipCurrentTag(parser);
8316 }
8317 }
8318
8319 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
8320 XmlPullParser parser)
8321 throws IOException, XmlPullParserException {
8322 int outerDepth = parser.getDepth();
8323 int type;
8324 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8325 && (type != XmlPullParser.END_TAG
8326 || parser.getDepth() > outerDepth)) {
8327 if (type == XmlPullParser.END_TAG
8328 || type == XmlPullParser.TEXT) {
8329 continue;
8330 }
8331
8332 String tagName = parser.getName();
8333 if (tagName.equals("item")) {
8334 String name = parser.getAttributeValue(null, "name");
8335 if (name != null) {
8336 packageSetting.enabledComponents.add(name.intern());
8337 } else {
8338 reportSettingsProblem(Log.WARN,
8339 "Error in package manager settings: <enabled-components> has"
8340 + " no name at " + parser.getPositionDescription());
8341 }
8342 } else {
8343 reportSettingsProblem(Log.WARN,
8344 "Unknown element under <enabled-components>: "
8345 + parser.getName());
8346 }
8347 XmlUtils.skipCurrentTag(parser);
8348 }
8349 }
8350
8351 private void readSharedUserLP(XmlPullParser parser)
8352 throws XmlPullParserException, IOException {
8353 String name = null;
8354 String idStr = null;
8355 int pkgFlags = 0;
8356 SharedUserSetting su = null;
8357 try {
8358 name = parser.getAttributeValue(null, "name");
8359 idStr = parser.getAttributeValue(null, "userId");
8360 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8361 if ("true".equals(parser.getAttributeValue(null, "system"))) {
8362 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8363 }
8364 if (name == null) {
8365 reportSettingsProblem(Log.WARN,
8366 "Error in package manager settings: <shared-user> has no name at "
8367 + parser.getPositionDescription());
8368 } else if (userId == 0) {
8369 reportSettingsProblem(Log.WARN,
8370 "Error in package manager settings: shared-user "
8371 + name + " has bad userId " + idStr + " at "
8372 + parser.getPositionDescription());
8373 } else {
8374 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
8375 reportSettingsProblem(Log.ERROR,
8376 "Occurred while parsing settings at "
8377 + parser.getPositionDescription());
8378 }
8379 }
8380 } catch (NumberFormatException e) {
8381 reportSettingsProblem(Log.WARN,
8382 "Error in package manager settings: package "
8383 + name + " has bad userId " + idStr + " at "
8384 + parser.getPositionDescription());
8385 };
8386
8387 if (su != null) {
8388 int outerDepth = parser.getDepth();
8389 int type;
8390 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8391 && (type != XmlPullParser.END_TAG
8392 || parser.getDepth() > outerDepth)) {
8393 if (type == XmlPullParser.END_TAG
8394 || type == XmlPullParser.TEXT) {
8395 continue;
8396 }
8397
8398 String tagName = parser.getName();
8399 if (tagName.equals("sigs")) {
8400 su.signatures.readXml(parser, mPastSignatures);
8401 } else if (tagName.equals("perms")) {
8402 readGrantedPermissionsLP(parser, su.loadedPermissions);
8403 } else {
8404 reportSettingsProblem(Log.WARN,
8405 "Unknown element under <shared-user>: "
8406 + parser.getName());
8407 XmlUtils.skipCurrentTag(parser);
8408 }
8409 }
8410
8411 } else {
8412 XmlUtils.skipCurrentTag(parser);
8413 }
8414 }
8415
8416 private void readGrantedPermissionsLP(XmlPullParser parser,
8417 HashSet<String> outPerms) throws IOException, XmlPullParserException {
8418 int outerDepth = parser.getDepth();
8419 int type;
8420 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8421 && (type != XmlPullParser.END_TAG
8422 || parser.getDepth() > outerDepth)) {
8423 if (type == XmlPullParser.END_TAG
8424 || type == XmlPullParser.TEXT) {
8425 continue;
8426 }
8427
8428 String tagName = parser.getName();
8429 if (tagName.equals("item")) {
8430 String name = parser.getAttributeValue(null, "name");
8431 if (name != null) {
8432 outPerms.add(name.intern());
8433 } else {
8434 reportSettingsProblem(Log.WARN,
8435 "Error in package manager settings: <perms> has"
8436 + " no name at " + parser.getPositionDescription());
8437 }
8438 } else {
8439 reportSettingsProblem(Log.WARN,
8440 "Unknown element under <perms>: "
8441 + parser.getName());
8442 }
8443 XmlUtils.skipCurrentTag(parser);
8444 }
8445 }
8446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008447 private void readPreferredActivitiesLP(XmlPullParser parser)
8448 throws XmlPullParserException, IOException {
8449 int outerDepth = parser.getDepth();
8450 int type;
8451 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8452 && (type != XmlPullParser.END_TAG
8453 || parser.getDepth() > outerDepth)) {
8454 if (type == XmlPullParser.END_TAG
8455 || type == XmlPullParser.TEXT) {
8456 continue;
8457 }
8458
8459 String tagName = parser.getName();
8460 if (tagName.equals("item")) {
8461 PreferredActivity pa = new PreferredActivity(parser);
8462 if (pa.mParseError == null) {
8463 mPreferredActivities.addFilter(pa);
8464 } else {
8465 reportSettingsProblem(Log.WARN,
8466 "Error in package manager settings: <preferred-activity> "
8467 + pa.mParseError + " at "
8468 + parser.getPositionDescription());
8469 }
8470 } else {
8471 reportSettingsProblem(Log.WARN,
8472 "Unknown element under <preferred-activities>: "
8473 + parser.getName());
8474 XmlUtils.skipCurrentTag(parser);
8475 }
8476 }
8477 }
8478
8479 // Returns -1 if we could not find an available UserId to assign
8480 private int newUserIdLP(Object obj) {
8481 // Let's be stupidly inefficient for now...
8482 final int N = mUserIds.size();
8483 for (int i=0; i<N; i++) {
8484 if (mUserIds.get(i) == null) {
8485 mUserIds.set(i, obj);
8486 return FIRST_APPLICATION_UID + i;
8487 }
8488 }
8489
8490 // None left?
8491 if (N >= MAX_APPLICATION_UIDS) {
8492 return -1;
8493 }
8494
8495 mUserIds.add(obj);
8496 return FIRST_APPLICATION_UID + N;
8497 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008499 public PackageSetting getDisabledSystemPkg(String name) {
8500 synchronized(mPackages) {
8501 PackageSetting ps = mDisabledSysPackages.get(name);
8502 return ps;
8503 }
8504 }
8505
8506 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
8507 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
8508 if (Config.LOGV) {
8509 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
8510 + " componentName = " + componentInfo.name);
8511 Log.v(TAG, "enabledComponents: "
8512 + Arrays.toString(packageSettings.enabledComponents.toArray()));
8513 Log.v(TAG, "disabledComponents: "
8514 + Arrays.toString(packageSettings.disabledComponents.toArray()));
8515 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008516 if (packageSettings == null) {
8517 if (false) {
8518 Log.w(TAG, "WAITING FOR DEBUGGER");
8519 Debug.waitForDebugger();
8520 Log.i(TAG, "We will crash!");
8521 }
8522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008523 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
8524 || ((componentInfo.enabled
8525 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
8526 || (componentInfo.applicationInfo.enabled
8527 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
8528 && !packageSettings.disabledComponents.contains(componentInfo.name))
8529 || packageSettings.enabledComponents.contains(componentInfo.name));
8530 }
8531 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008532
8533 // ------- apps on sdcard specific code -------
8534 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08008535 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08008536 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008537 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008538 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008539
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008540 private String getEncryptKey() {
8541 try {
8542 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8543 if (sdEncKey == null) {
8544 sdEncKey = SystemKeyStore.getInstance().
8545 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
8546 if (sdEncKey == null) {
8547 Log.e(TAG, "Failed to create encryption keys");
8548 return null;
8549 }
8550 }
8551 return sdEncKey;
8552 } catch (NoSuchAlgorithmException nsae) {
8553 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
8554 return null;
8555 }
8556 }
8557
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008558 static String getTempContainerId() {
8559 String prefix = "smdl1tmp";
8560 int tmpIdx = 1;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008561 String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008562 if (list != null) {
8563 int idx = 0;
8564 int idList[] = new int[MAX_CONTAINERS];
8565 boolean neverFound = true;
8566 for (String name : list) {
8567 // Ignore null entries
8568 if (name == null) {
8569 continue;
8570 }
8571 int sidx = name.indexOf(prefix);
8572 if (sidx == -1) {
8573 // Not a temp file. just ignore
8574 continue;
8575 }
8576 String subStr = name.substring(sidx + prefix.length());
8577 idList[idx] = -1;
8578 if (subStr != null) {
8579 try {
8580 int cid = Integer.parseInt(subStr);
8581 idList[idx++] = cid;
8582 neverFound = false;
8583 } catch (NumberFormatException e) {
8584 }
8585 }
8586 }
8587 if (!neverFound) {
8588 // Sort idList
8589 Arrays.sort(idList);
8590 for (int j = 1; j <= idList.length; j++) {
8591 if (idList[j-1] != j) {
8592 tmpIdx = j;
8593 break;
8594 }
8595 }
8596 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008597 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008598 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008599 }
8600
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008601 public void updateExternalMediaStatus(final boolean mediaStatus) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008602 synchronized (mPackages) {
8603 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
8604 mediaStatus+", mMediaMounted=" + mMediaMounted);
8605 if (mediaStatus == mMediaMounted) {
8606 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008607 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008608 mMediaMounted = mediaStatus;
8609 // Queue up an async operation since the package installation may take a little while.
8610 mHandler.post(new Runnable() {
8611 public void run() {
8612 mHandler.removeCallbacks(this);
8613 updateExternalMediaStatusInner(mediaStatus);
8614 }
8615 });
8616 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008617 }
8618
8619 void updateExternalMediaStatusInner(boolean mediaStatus) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08008620 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008621 if (list == null || list.length == 0) {
8622 return;
8623 }
8624 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
8625 int uidList[] = new int[list.length];
8626 int num = 0;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008627 synchronized (mPackages) {
8628 Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
8629 for (String cid : list) {
8630 SdInstallArgs args = new SdInstallArgs(cid);
8631 String removeEntry = null;
8632 for (String app : appList) {
8633 if (args.matchContainer(app)) {
8634 removeEntry = app;
8635 break;
8636 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008637 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008638 if (removeEntry == null) {
8639 // No matching app on device. Skip entry or may be cleanup?
8640 // Ignore default package
8641 continue;
8642 }
8643 appList.remove(removeEntry);
8644 PackageSetting ps = mSettings.mPackages.get(removeEntry);
8645 processCids.put(args, ps.codePathString);
8646 int uid = ps.userId;
8647 if (uid != -1) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008648 uidList[num++] = uid;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008649 }
8650 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008651 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008652 int uidArr[] = null;
8653 if (num > 0) {
8654 // Sort uid list
8655 Arrays.sort(uidList, 0, num);
8656 // Throw away duplicates
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008657 uidArr = new int[num];
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008658 uidArr[0] = uidList[0];
8659 int di = 0;
8660 for (int i = 1; i < num; i++) {
8661 if (uidList[i-1] != uidList[i]) {
8662 uidArr[di++] = uidList[i];
8663 }
8664 }
8665 if (true) {
8666 for (int j = 0; j < num; j++) {
8667 Log.i(TAG, "uidArr[" + j + "]=" + uidArr[j]);
8668 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008669 }
8670 }
8671 if (mediaStatus) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008672 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008673 loadMediaPackages(processCids, uidArr);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008674 startCleaningPackages();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008675 } else {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008676 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008677 unloadMediaPackages(processCids, uidArr);
8678 }
8679 }
8680
8681 private void sendResourcesChangedBroadcast(boolean mediaStatus,
8682 ArrayList<String> pkgList, int uidArr[]) {
8683 int size = pkgList.size();
8684 if (size > 0) {
8685 // Send broadcasts here
8686 Bundle extras = new Bundle();
8687 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
8688 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008689 if (uidArr != null) {
8690 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
8691 }
8692 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
8693 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008694 sendPackageBroadcast(action, null, extras);
8695 }
8696 }
8697
8698 void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
8699 ArrayList<String> pkgList = new ArrayList<String>();
8700 Set<SdInstallArgs> keys = processCids.keySet();
8701 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008702 String codePath = processCids.get(args);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008703 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install pkg : "
8704 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008705 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008706 Log.e(TAG, "Failed to install package: " + codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008707 continue;
8708 }
8709 // Parse package
8710 int parseFlags = PackageParser.PARSE_CHATTY |
8711 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8712 PackageParser pp = new PackageParser(codePath);
8713 pp.setSeparateProcesses(mSeparateProcesses);
8714 final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
8715 codePath, mMetrics, parseFlags);
8716 if (pkg == null) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008717 Log.e(TAG, "Trying to install pkg : "
8718 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008719 continue;
8720 }
8721 setApplicationInfoPaths(pkg, codePath, codePath);
8722 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8723 synchronized (mInstallLock) {
8724 // Scan the package
8725 if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
8726 synchronized (mPackages) {
8727 // Grant permissions
8728 grantPermissionsLP(pkg, false);
8729 // Persist settings
8730 mSettings.writeLP();
8731 retCode = PackageManager.INSTALL_SUCCEEDED;
8732 pkgList.add(pkg.packageName);
8733 }
8734 } else {
8735 Log.i(TAG, "Failed to install package: " + pkg.packageName + " from sdcard");
8736 }
8737 }
8738 args.doPostInstall(retCode);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008739 }
8740 // Send broadcasts first
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008741 if (pkgList.size() > 0) {
8742 sendResourcesChangedBroadcast(true, pkgList, uidArr);
8743 Runtime.getRuntime().gc();
8744 // If something failed do we clean up here or next install?
8745 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008746 }
8747
8748 void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008749 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008750 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008751 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008752 Set<SdInstallArgs> keys = processCids.keySet();
8753 for (SdInstallArgs args : keys) {
8754 String cid = args.cid;
8755 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008756 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008757 // Delete package internally
8758 PackageRemovedInfo outInfo = new PackageRemovedInfo();
8759 synchronized (mInstallLock) {
8760 boolean res = deletePackageLI(pkgName, false,
8761 PackageManager.DONT_DELETE_DATA, outInfo);
8762 if (res) {
8763 pkgList.add(pkgName);
8764 } else {
8765 Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008766 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008767 }
8768 }
8769 }
8770 // Send broadcasts
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008771 if (pkgList.size() > 0) {
8772 sendResourcesChangedBroadcast(false, pkgList, uidArr);
8773 Runtime.getRuntime().gc();
8774 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008775 // Do clean up. Just unmount
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008776 for (SdInstallArgs args : failedList) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008777 synchronized (mInstallLock) {
8778 args.doPostDeleteLI(false);
8779 }
8780 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008782}