blob: b1bd263cdee5ac3b5e7e1d0ffd50a86182293bc7 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080019import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.app.ResolverActivity;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -080021import com.android.internal.content.PackageHelper;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080022import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070023import com.android.internal.util.JournaledFile;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080024import com.android.internal.util.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025
26import org.xmlpull.v1.XmlPullParser;
27import org.xmlpull.v1.XmlPullParserException;
28import org.xmlpull.v1.XmlSerializer;
29
30import android.app.ActivityManagerNative;
31import android.app.IActivityManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080032import android.app.admin.IDevicePolicyManager;
Christopher Tate45281862010-03-05 15:46:30 -080033import android.app.backup.IBackupManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.Context;
36import android.content.Intent;
37import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070038import android.content.IntentSender;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080039import android.content.ServiceConnection;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070040import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.content.pm.ActivityInfo;
42import android.content.pm.ApplicationInfo;
43import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070044import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.content.pm.IPackageDataObserver;
46import android.content.pm.IPackageDeleteObserver;
47import android.content.pm.IPackageInstallObserver;
48import android.content.pm.IPackageManager;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080049import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.content.pm.IPackageStatsObserver;
51import android.content.pm.InstrumentationInfo;
52import android.content.pm.PackageInfo;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -080053import android.content.pm.PackageInfoLite;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.content.pm.PackageManager;
55import android.content.pm.PackageStats;
56import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
57import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
58import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.pm.PackageParser;
60import android.content.pm.PermissionInfo;
61import android.content.pm.PermissionGroupInfo;
62import android.content.pm.ProviderInfo;
63import android.content.pm.ResolveInfo;
64import android.content.pm.ServiceInfo;
65import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.net.Uri;
67import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070068import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080070import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080072import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070073import android.os.Looper;
74import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.Parcel;
76import android.os.RemoteException;
77import android.os.Environment;
78import android.os.FileObserver;
79import android.os.FileUtils;
80import android.os.Handler;
81import android.os.ParcelFileDescriptor;
82import android.os.Process;
83import android.os.ServiceManager;
84import android.os.SystemClock;
85import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080086import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.util.*;
88import android.view.Display;
89import android.view.WindowManager;
90
91import java.io.File;
92import java.io.FileDescriptor;
93import java.io.FileInputStream;
94import java.io.FileNotFoundException;
95import java.io.FileOutputStream;
96import java.io.FileReader;
97import java.io.FilenameFilter;
98import java.io.IOException;
99import java.io.InputStream;
100import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -0800101import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800102import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import java.util.ArrayList;
104import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700105import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.Collections;
107import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800108import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.util.Enumeration;
110import java.util.HashMap;
111import java.util.HashSet;
112import java.util.Iterator;
113import java.util.List;
114import java.util.Map;
115import java.util.Set;
116import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800117import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.util.zip.ZipFile;
119import java.util.zip.ZipOutputStream;
120
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700121/**
122 * Keep track of all those .apks everywhere.
123 *
124 * This is very central to the platform's security; please run the unit
125 * tests whenever making modifications here:
126 *
127mmm frameworks/base/tests/AndroidTests
128adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
129adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
130 *
131 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132class PackageManagerService extends IPackageManager.Stub {
133 private static final String TAG = "PackageManager";
134 private static final boolean DEBUG_SETTINGS = false;
135 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800136 private static final boolean DEBUG_UPGRADE = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800137 private static final boolean DEBUG_INSTALL = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
139 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
140 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400141 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 private static final int FIRST_APPLICATION_UID =
143 Process.FIRST_APPLICATION_UID;
144 private static final int MAX_APPLICATION_UIDS = 1000;
145
146 private static final boolean SHOW_INFO = false;
147
148 private static final boolean GET_CERTIFICATES = true;
149
150 private static final int REMOVE_EVENTS =
151 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
152 private static final int ADD_EVENTS =
153 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
154
155 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800156 // Suffix used during package installation when copying/moving
157 // package apks to install directory.
158 private static final String INSTALL_PACKAGE_SUFFIX = "-";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -0800160 /**
161 * Indicates the state of installation. Used by PackageManager to
162 * figure out incomplete installations. Say a package is being installed
163 * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
164 * the package installation is successful or unsuccesful lin which case
165 * the PackageManager will no longer maintain state information associated
166 * with the package. If some exception(like device freeze or battery being
167 * pulled out) occurs during installation of a package, the PackageManager
168 * needs this information to clean up the previously failed installation.
169 */
170 private static final int PKG_INSTALL_INCOMPLETE = 0;
171 private static final int PKG_INSTALL_COMPLETE = 1;
172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 static final int SCAN_MONITOR = 1<<0;
174 static final int SCAN_NO_DEX = 1<<1;
175 static final int SCAN_FORCE_DEX = 1<<2;
176 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800177 static final int SCAN_NEW_INSTALL = 1<<4;
178 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800180 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
181 "com.android.defcontainer",
182 "com.android.defcontainer.DefaultContainerService");
183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
185 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700186 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187
Dianne Hackborn851a5412009-05-08 12:06:44 -0700188 final int mSdkVersion = Build.VERSION.SDK_INT;
189 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
190 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 final Context mContext;
193 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700194 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 final DisplayMetrics mMetrics;
196 final int mDefParseFlags;
197 final String[] mSeparateProcesses;
198
199 // This is where all application persistent data goes.
200 final File mAppDataDir;
201
202 // This is the object monitoring the framework dir.
203 final FileObserver mFrameworkInstallObserver;
204
205 // This is the object monitoring the system app dir.
206 final FileObserver mSystemInstallObserver;
207
208 // This is the object monitoring mAppInstallDir.
209 final FileObserver mAppInstallObserver;
210
211 // This is the object monitoring mDrmAppPrivateInstallDir.
212 final FileObserver mDrmAppInstallObserver;
213
214 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
215 // LOCK HELD. Can be called with mInstallLock held.
216 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 final File mFrameworkDir;
219 final File mSystemAppDir;
220 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700221 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
223 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
224 // apps.
225 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 // Lock for state used when installing and doing other long running
230 // operations. Methods that must be called with this lock held have
231 // the prefix "LI".
232 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 // These are the directories in the 3rd party applications installed dir
235 // that we have currently loaded packages from. Keys are the application's
236 // installed zip file (absolute codePath), and values are Package.
237 final HashMap<String, PackageParser.Package> mAppDirs =
238 new HashMap<String, PackageParser.Package>();
239
240 // Information for the parser to write more useful error messages.
241 File mScanningPath;
242 int mLastScanError;
243
244 final int[] mOutPermissions = new int[3];
245
246 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 // Keys are String (package name), values are Package. This also serves
249 // as the lock for the global state. Methods that must be called with
250 // this lock held have the prefix "LP".
251 final HashMap<String, PackageParser.Package> mPackages =
252 new HashMap<String, PackageParser.Package>();
253
254 final Settings mSettings;
255 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256
257 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
258 int[] mGlobalGids;
259
260 // These are the built-in uid -> permission mappings that were read from the
261 // etc/permissions.xml file.
262 final SparseArray<HashSet<String>> mSystemPermissions =
263 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 // These are the built-in shared libraries that were read from the
266 // etc/permissions.xml file.
267 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800268
Dianne Hackborn49237342009-08-27 20:08:01 -0700269 // Temporary for building the final shared libraries for an .apk.
270 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800271
Dianne Hackborn49237342009-08-27 20:08:01 -0700272 // These are the features this devices supports that were read from the
273 // etc/permissions.xml file.
274 final HashMap<String, FeatureInfo> mAvailableFeatures =
275 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 // All available activities, for your resolving pleasure.
278 final ActivityIntentResolver mActivities =
279 new ActivityIntentResolver();
280
281 // All available receivers, for your resolving pleasure.
282 final ActivityIntentResolver mReceivers =
283 new ActivityIntentResolver();
284
285 // All available services, for your resolving pleasure.
286 final ServiceIntentResolver mServices = new ServiceIntentResolver();
287
288 // Keys are String (provider class name), values are Provider.
289 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
290 new HashMap<ComponentName, PackageParser.Provider>();
291
292 // Mapping from provider base names (first directory in content URI codePath)
293 // to the provider information.
294 final HashMap<String, PackageParser.Provider> mProviders =
295 new HashMap<String, PackageParser.Provider>();
296
297 // Mapping from instrumentation class names to info about them.
298 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
299 new HashMap<ComponentName, PackageParser.Instrumentation>();
300
301 // Mapping from permission names to info about them.
302 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
303 new HashMap<String, PackageParser.PermissionGroup>();
304
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800305 // Packages whose data we have transfered into another package, thus
306 // should no longer exist.
307 final HashSet<String> mTransferedPackages = new HashSet<String>();
308
Dianne Hackborn854060af2009-07-09 18:14:31 -0700309 // Broadcast actions that are only available to the system.
310 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 boolean mSystemReady;
313 boolean mSafeMode;
314 boolean mHasSystemUidErrors;
315
316 ApplicationInfo mAndroidApplication;
317 final ActivityInfo mResolveActivity = new ActivityInfo();
318 final ResolveInfo mResolveInfo = new ResolveInfo();
319 ComponentName mResolveComponentName;
320 PackageParser.Package mPlatformPackage;
321
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700322 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800323 final HashMap<String, ArrayList<String>> mPendingBroadcasts
324 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800325 // Service Connection to remote media container service to copy
326 // package uri's from external media onto secure containers
327 // or internal storage.
328 private IMediaContainerService mContainerService = null;
329
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700330 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800331 static final int MCS_BOUND = 3;
332 static final int END_COPY = 4;
333 static final int INIT_COPY = 5;
334 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800335 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800336 static final int FIND_INSTALL_LOC = 8;
Christopher Tate1bb69062010-02-19 17:02:12 -0800337 static final int POST_INSTALL = 9;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800338 static final int MCS_RECONNECT = 10;
339 static final int MCS_GIVE_UP = 11;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700340 static final int UPDATED_MEDIA_STATUS = 12;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700341 static final int WRITE_SETTINGS = 13;
342
343 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800344
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700345 // Delay time in millisecs
346 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800347 final private DefaultContainerConnection mDefContainerConn =
348 new DefaultContainerConnection();
349 class DefaultContainerConnection implements ServiceConnection {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800350 public void onServiceConnected(ComponentName name, IBinder service) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800351 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800352 IMediaContainerService imcs =
353 IMediaContainerService.Stub.asInterface(service);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800354 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs));
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800355 }
356
357 public void onServiceDisconnected(ComponentName name) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800358 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800359 }
360 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700361
Christopher Tate1bb69062010-02-19 17:02:12 -0800362 // Recordkeeping of restore-after-install operations that are currently in flight
363 // between the Package Manager and the Backup Manager
364 class PostInstallData {
365 public InstallArgs args;
366 public PackageInstalledInfo res;
367
368 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
369 args = _a;
370 res = _r;
371 }
372 };
373 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
374 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
375
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700376 class PackageHandler extends Handler {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800377 private boolean mBound = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800378 final ArrayList<HandlerParams> mPendingInstalls =
379 new ArrayList<HandlerParams>();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800380
381 private boolean connectToService() {
382 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" +
383 " DefaultContainerService");
384 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700385 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800386 if (mContext.bindService(service, mDefContainerConn,
387 Context.BIND_AUTO_CREATE)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700388 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800389 mBound = true;
390 return true;
391 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700392 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800393 return false;
394 }
395
396 private void disconnectService() {
397 mContainerService = null;
398 mBound = false;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700399 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800400 mContext.unbindService(mDefContainerConn);
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700401 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800402 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800403
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700404 PackageHandler(Looper looper) {
405 super(looper);
406 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700407
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700408 public void handleMessage(Message msg) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700409 try {
410 doHandleMessage(msg);
411 } finally {
412 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
413 }
414 }
415
416 void doHandleMessage(Message msg) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700417 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800418 case INIT_COPY: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800419 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -0800420 HandlerParams params = (HandlerParams) msg.obj;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800421 int idx = mPendingInstalls.size();
422 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
423 // If a bind was already initiated we dont really
424 // need to do anything. The pending install
425 // will be processed later on.
426 if (!mBound) {
427 // If this is the only one pending we might
428 // have to bind to the service again.
429 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800430 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800431 params.serviceError();
432 return;
433 } else {
434 // Once we bind to the service, the first
435 // pending request will be processed.
436 mPendingInstalls.add(idx, params);
437 }
438 } else {
439 mPendingInstalls.add(idx, params);
440 // Already bound to the service. Just make
441 // sure we trigger off processing the first request.
442 if (idx == 0) {
443 mHandler.sendEmptyMessage(MCS_BOUND);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800444 }
445 }
446 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800447 }
448 case MCS_BOUND: {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800449 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800450 if (msg.obj != null) {
451 mContainerService = (IMediaContainerService) msg.obj;
452 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800453 if (mContainerService == null) {
454 // Something seriously wrong. Bail out
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800455 Slog.e(TAG, "Cannot bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800456 for (HandlerParams params : mPendingInstalls) {
457 mPendingInstalls.remove(0);
458 // Indicate service bind error
459 params.serviceError();
460 }
461 mPendingInstalls.clear();
462 } else if (mPendingInstalls.size() > 0) {
463 HandlerParams params = mPendingInstalls.get(0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -0800464 if (params != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800465 params.startCopy();
466 }
467 } else {
468 // Should never happen ideally.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800469 Slog.w(TAG, "Empty queue");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800470 }
471 break;
472 }
473 case MCS_RECONNECT : {
474 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
475 if (mPendingInstalls.size() > 0) {
476 if (mBound) {
477 disconnectService();
478 }
479 if (!connectToService()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800480 Slog.e(TAG, "Failed to bind to media container service");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800481 for (HandlerParams params : mPendingInstalls) {
482 mPendingInstalls.remove(0);
483 // Indicate service bind error
484 params.serviceError();
485 }
486 mPendingInstalls.clear();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800487 }
488 }
489 break;
490 }
491 case MCS_UNBIND : {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800492 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
493 // Delete pending install
494 if (mPendingInstalls.size() > 0) {
495 mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800496 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -0800497 if (mPendingInstalls.size() == 0) {
498 if (mBound) {
499 disconnectService();
500 }
501 } else {
502 // There are more pending requests in queue.
503 // Just post MCS_BOUND message to trigger processing
504 // of next pending install.
505 mHandler.sendEmptyMessage(MCS_BOUND);
506 }
507 break;
508 }
509 case MCS_GIVE_UP: {
510 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
511 HandlerParams params = mPendingInstalls.remove(0);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800512 break;
513 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700514 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800515 String packages[];
516 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700517 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700518 int uids[];
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700519 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700520 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800521 if (mPendingBroadcasts == null) {
522 return;
523 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700524 size = mPendingBroadcasts.size();
525 if (size <= 0) {
526 // Nothing to be done. Just return
527 return;
528 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800529 packages = new String[size];
530 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700531 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800532 Iterator<HashMap.Entry<String, ArrayList<String>>>
533 it = mPendingBroadcasts.entrySet().iterator();
534 int i = 0;
535 while (it.hasNext() && i < size) {
536 HashMap.Entry<String, ArrayList<String>> ent = it.next();
537 packages[i] = ent.getKey();
538 components[i] = ent.getValue();
539 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700540 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800541 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700542 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800543 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700544 mPendingBroadcasts.clear();
545 }
546 // Send broadcasts
547 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800548 sendPackageChangedBroadcast(packages[i], true,
549 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700550 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700551 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700552 break;
553 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800554 case START_CLEANING_PACKAGE: {
555 String packageName = (String)msg.obj;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700556 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800557 synchronized (mPackages) {
558 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
559 mSettings.mPackagesToBeCleaned.add(packageName);
560 }
561 }
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700562 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800563 startCleaningPackages();
564 } break;
Christopher Tate1bb69062010-02-19 17:02:12 -0800565 case POST_INSTALL: {
566 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
567 PostInstallData data = mRunningInstalls.get(msg.arg1);
568 mRunningInstalls.delete(msg.arg1);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800569 boolean deleteOld = false;
Christopher Tate1bb69062010-02-19 17:02:12 -0800570
571 if (data != null) {
572 InstallArgs args = data.args;
573 PackageInstalledInfo res = data.res;
574
575 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
576 res.removedInfo.sendBroadcast(false, true);
577 Bundle extras = new Bundle(1);
578 extras.putInt(Intent.EXTRA_UID, res.uid);
579 final boolean update = res.removedInfo.removedPackage != null;
580 if (update) {
581 extras.putBoolean(Intent.EXTRA_REPLACING, true);
582 }
583 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
584 res.pkg.applicationInfo.packageName,
585 extras);
586 if (update) {
587 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
588 res.pkg.applicationInfo.packageName,
589 extras);
590 }
591 if (res.removedInfo.args != null) {
592 // Remove the replaced package's older resources safely now
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800593 deleteOld = true;
Christopher Tate1bb69062010-02-19 17:02:12 -0800594 }
595 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800596 // Force a gc to clear up things
Christopher Tate1bb69062010-02-19 17:02:12 -0800597 Runtime.getRuntime().gc();
Suchi Amalapurapud32c8022010-03-04 17:18:14 -0800598 // We delete after a gc for applications on sdcard.
599 if (deleteOld) {
600 synchronized (mInstallLock) {
601 res.removedInfo.args.doPostDeleteLI(true);
602 }
603 }
Christopher Tate1bb69062010-02-19 17:02:12 -0800604 if (args.observer != null) {
605 try {
606 args.observer.packageInstalled(res.name, res.returnCode);
607 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800608 Slog.i(TAG, "Observer no longer exists.");
Christopher Tate1bb69062010-02-19 17:02:12 -0800609 }
610 }
611 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800612 Slog.e(TAG, "Bogus post-install token " + msg.arg1);
Christopher Tate1bb69062010-02-19 17:02:12 -0800613 }
614 } break;
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -0700615 case UPDATED_MEDIA_STATUS: {
616 try {
617 PackageHelper.getMountService().finishMediaUpdate();
618 } catch (RemoteException e) {
619 Log.e(TAG, "MountService not running?");
620 }
621 } break;
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700622 case WRITE_SETTINGS: {
623 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
624 synchronized (mPackages) {
625 removeMessages(WRITE_SETTINGS);
626 mSettings.writeLP();
627 }
628 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
629 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700630 }
631 }
632 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800633
Dianne Hackbornd7c09682010-03-30 10:42:20 -0700634 void scheduleWriteSettingsLocked() {
635 if (!mHandler.hasMessages(WRITE_SETTINGS)) {
636 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
637 }
638 }
639
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800640 static boolean installOnSd(int flags) {
641 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700642 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800643 return false;
644 }
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -0700645 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
646 return true;
647 }
648 return false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800649 }
650
651 static boolean isFwdLocked(int flags) {
652 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
653 return true;
654 }
655 return false;
656 }
657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 public static final IPackageManager main(Context context, boolean factoryTest) {
659 PackageManagerService m = new PackageManagerService(context, factoryTest);
660 ServiceManager.addService("package", m);
661 return m;
662 }
663
664 static String[] splitString(String str, char sep) {
665 int count = 1;
666 int i = 0;
667 while ((i=str.indexOf(sep, i)) >= 0) {
668 count++;
669 i++;
670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 String[] res = new String[count];
673 i=0;
674 count = 0;
675 int lastI=0;
676 while ((i=str.indexOf(sep, i)) >= 0) {
677 res[count] = str.substring(lastI, i);
678 count++;
679 i++;
680 lastI = i;
681 }
682 res[count] = str.substring(lastI, str.length());
683 return res;
684 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800687 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 if (mSdkVersion <= 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800691 Slog.w(TAG, "**** ro.build.version.sdk not set!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 mContext = context;
695 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700696 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 mMetrics = new DisplayMetrics();
698 mSettings = new Settings();
699 mSettings.addSharedUserLP("android.uid.system",
700 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
701 mSettings.addSharedUserLP("android.uid.phone",
702 MULTIPLE_APPLICATION_UIDS
703 ? RADIO_UID : FIRST_APPLICATION_UID,
704 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400705 mSettings.addSharedUserLP("android.uid.log",
706 MULTIPLE_APPLICATION_UIDS
707 ? LOG_UID : FIRST_APPLICATION_UID,
708 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
710 String separateProcesses = SystemProperties.get("debug.separate_processes");
711 if (separateProcesses != null && separateProcesses.length() > 0) {
712 if ("*".equals(separateProcesses)) {
713 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
714 mSeparateProcesses = null;
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800715 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 } else {
717 mDefParseFlags = 0;
718 mSeparateProcesses = separateProcesses.split(",");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800719 Slog.w(TAG, "Running with debug.separate_processes: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 + separateProcesses);
721 }
722 } else {
723 mDefParseFlags = 0;
724 mSeparateProcesses = null;
725 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 Installer installer = new Installer();
728 // Little hacky thing to check if installd is here, to determine
729 // whether we are running on the simulator and thus need to take
730 // care of building the /data file structure ourself.
731 // (apparently the sim now has a working installer)
732 if (installer.ping() && Process.supportsProcesses()) {
733 mInstaller = installer;
734 } else {
735 mInstaller = null;
736 }
737
738 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
739 Display d = wm.getDefaultDisplay();
740 d.getMetrics(mMetrics);
741
742 synchronized (mInstallLock) {
743 synchronized (mPackages) {
744 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700745 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 File dataDir = Environment.getDataDirectory();
748 mAppDataDir = new File(dataDir, "data");
749 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
750
751 if (mInstaller == null) {
752 // Make sure these dirs exist, when we are running in
753 // the simulator.
754 // Make a wide-open directory for random misc stuff.
755 File miscDir = new File(dataDir, "misc");
756 miscDir.mkdirs();
757 mAppDataDir.mkdirs();
758 mDrmAppPrivateInstallDir.mkdirs();
759 }
760
761 readPermissions();
762
763 mRestoredSettings = mSettings.readLP();
764 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800765
766 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800768
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800769 // Set flag to monitor and not change apk file paths when
770 // scanning install directories.
771 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700772 if (mNoDexOpt) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800773 Slog.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800774 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700775 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700780 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700783 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 /**
786 * Out of paranoia, ensure that everything in the boot class
787 * path has been dexed.
788 */
789 String bootClassPath = System.getProperty("java.boot.class.path");
790 if (bootClassPath != null) {
791 String[] paths = splitString(bootClassPath, ':');
792 for (int i=0; i<paths.length; i++) {
793 try {
794 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
795 libFiles.add(paths[i]);
796 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700797 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 }
799 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800800 Slog.w(TAG, "Boot class path not found: " + paths[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800802 Slog.w(TAG, "Exception reading boot class path: " + paths[i], e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 }
804 }
805 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800806 Slog.w(TAG, "No BOOTCLASSPATH found!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 /**
810 * Also ensure all external libraries have had dexopt run on them.
811 */
812 if (mSharedLibraries.size() > 0) {
813 Iterator<String> libs = mSharedLibraries.values().iterator();
814 while (libs.hasNext()) {
815 String lib = libs.next();
816 try {
817 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
818 libFiles.add(lib);
819 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700820 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
822 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800823 Slog.w(TAG, "Library not found: " + lib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800825 Slog.w(TAG, "Exception reading library: " + lib, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 }
827 }
828 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 // Gross hack for now: we know this file doesn't contain any
831 // code, so don't dexopt it to avoid the resulting log spew.
832 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 /**
835 * And there are a number of commands implemented in Java, which
836 * we currently need to do the dexopt on so that they can be
837 * run from a non-root shell.
838 */
839 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700840 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 for (int i=0; i<frameworkFiles.length; i++) {
842 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
843 String path = libPath.getPath();
844 // Skip the file if we alrady did it.
845 if (libFiles.contains(path)) {
846 continue;
847 }
848 // Skip the file if it is not a type we want to dexopt.
849 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
850 continue;
851 }
852 try {
853 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
854 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700855 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 }
857 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800858 Slog.w(TAG, "Jar not found: " + path);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800860 Slog.w(TAG, "Exception reading jar: " + path, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
862 }
863 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800864
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700865 if (didDexOpt) {
866 // If we had to do a dexopt of one of the previous
867 // things, then something on the system has changed.
868 // Consider this significant, and wipe away all other
869 // existing dexopt files to ensure we don't leave any
870 // dangling around.
871 String[] files = mDalvikCacheDir.list();
872 if (files != null) {
873 for (int i=0; i<files.length; i++) {
874 String fn = files[i];
875 if (fn.startsWith("data@app@")
876 || fn.startsWith("data@app-private@")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800877 Slog.i(TAG, "Pruning dalvik file: " + fn);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700878 (new File(mDalvikCacheDir, fn)).delete();
879 }
880 }
881 }
882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800884
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800885 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 mFrameworkInstallObserver = new AppDirObserver(
887 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
888 mFrameworkInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700889 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
890 | PackageParser.PARSE_IS_SYSTEM_DIR,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800891 scanMode | SCAN_NO_DEX);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800892
893 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
895 mSystemInstallObserver = new AppDirObserver(
896 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
897 mSystemInstallObserver.startWatching();
Dianne Hackborn806da1d2010-03-18 16:50:07 -0700898 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
899 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800900
901 if (mInstaller != null) {
902 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
903 mInstaller.moveFiles();
904 }
905
906 // Prune any system packages that no longer exist.
907 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
908 while (psit.hasNext()) {
909 PackageSetting ps = psit.next();
910 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
Dianne Hackborn6dee18c2010-02-09 23:59:16 -0800911 && !mPackages.containsKey(ps.name)
912 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800913 psit.remove();
914 String msg = "System package " + ps.name
915 + " no longer exists; wiping its data";
916 reportSettingsProblem(Log.WARN, msg);
917 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -0700918 mInstaller.remove(ps.name);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800919 }
920 }
921 }
922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 mAppInstallDir = new File(dataDir, "app");
924 if (mInstaller == null) {
925 // Make sure these dirs exist, when we are running in
926 // the simulator.
927 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
928 }
929 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800930 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 //clean up list
932 for(int i = 0; i < deletePkgsList.size(); i++) {
933 //clean up here
934 cleanupInstallFailedPackage(deletePkgsList.get(i));
935 }
936 //delete tmp files
937 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800938
939 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 SystemClock.uptimeMillis());
941 mAppInstallObserver = new AppDirObserver(
942 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
943 mAppInstallObserver.startWatching();
944 scanDirLI(mAppInstallDir, 0, scanMode);
945
946 mDrmAppInstallObserver = new AppDirObserver(
947 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
948 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800949 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800951 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 SystemClock.uptimeMillis());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800953 Slog.i(TAG, "Time to scan packages: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 + ((SystemClock.uptimeMillis()-startTime)/1000f)
955 + " seconds");
956
Dianne Hackbornd4310ac2010-03-16 22:55:08 -0700957 updatePermissionsLP(null, null, true, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958
959 mSettings.writeLP();
960
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800961 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 // Now after opening every single application zip, make sure they
965 // are all flushed. Not really needed, but keeps things nice and
966 // tidy.
967 Runtime.getRuntime().gc();
968 } // synchronized (mPackages)
969 } // synchronized (mInstallLock)
970 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 @Override
973 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
974 throws RemoteException {
975 try {
976 return super.onTransact(code, data, reply, flags);
977 } catch (RuntimeException e) {
978 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800979 Slog.e(TAG, "Package Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 }
981 throw e;
982 }
983 }
984
Dianne Hackborne6620b22010-01-22 14:46:21 -0800985 void cleanupInstallFailedPackage(PackageSetting ps) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800986 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -0700988 int retCode = mInstaller.remove(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -0800990 Slog.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800991 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 }
993 } else {
994 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800995 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 File dataDir = new File(pkg.applicationInfo.dataDir);
997 dataDir.delete();
998 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800999 if (ps.codePath != null) {
1000 if (!ps.codePath.delete()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001001 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001002 }
1003 }
1004 if (ps.resourcePath != null) {
1005 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001006 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
Dianne Hackborne6620b22010-01-22 14:46:21 -08001007 }
1008 }
1009 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 }
1011
1012 void readPermissions() {
1013 // Read permissions from .../etc/permission directory.
1014 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
1015 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001016 Slog.w(TAG, "No directory " + libraryDir + ", skipping");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 return;
1018 }
1019 if (!libraryDir.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001020 Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 return;
1022 }
1023
1024 // Iterate over the files in the directory and scan .xml files
1025 for (File f : libraryDir.listFiles()) {
1026 // We'll read platform.xml last
1027 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
1028 continue;
1029 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 if (!f.getPath().endsWith(".xml")) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001032 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 continue;
1034 }
1035 if (!f.canRead()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001036 Slog.w(TAG, "Permissions library file " + f + " cannot be read");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 continue;
1038 }
1039
1040 readPermissionsFromXml(f);
1041 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
1044 final File permFile = new File(Environment.getRootDirectory(),
1045 "etc/permissions/platform.xml");
1046 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001047
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001048 StringBuilder sb = new StringBuilder(128);
1049 sb.append("Libs:");
1050 Iterator<String> it = mSharedLibraries.keySet().iterator();
1051 while (it.hasNext()) {
1052 sb.append(' ');
1053 String name = it.next();
1054 sb.append(name);
1055 sb.append(':');
1056 sb.append(mSharedLibraries.get(name));
1057 }
1058 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001059
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001060 sb.setLength(0);
1061 sb.append("Features:");
1062 it = mAvailableFeatures.keySet().iterator();
1063 while (it.hasNext()) {
1064 sb.append(' ');
1065 sb.append(it.next());
1066 }
1067 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001069
1070 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 FileReader permReader = null;
1072 try {
1073 permReader = new FileReader(permFile);
1074 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001075 Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 return;
1077 }
1078
1079 try {
1080 XmlPullParser parser = Xml.newPullParser();
1081 parser.setInput(permReader);
1082
1083 XmlUtils.beginDocument(parser, "permissions");
1084
1085 while (true) {
1086 XmlUtils.nextElement(parser);
1087 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
1088 break;
1089 }
1090
1091 String name = parser.getName();
1092 if ("group".equals(name)) {
1093 String gidStr = parser.getAttributeValue(null, "gid");
1094 if (gidStr != null) {
1095 int gid = Integer.parseInt(gidStr);
1096 mGlobalGids = appendInt(mGlobalGids, gid);
1097 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001098 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 + parser.getPositionDescription());
1100 }
1101
1102 XmlUtils.skipCurrentTag(parser);
1103 continue;
1104 } else if ("permission".equals(name)) {
1105 String perm = parser.getAttributeValue(null, "name");
1106 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001107 Slog.w(TAG, "<permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 + parser.getPositionDescription());
1109 XmlUtils.skipCurrentTag(parser);
1110 continue;
1111 }
1112 perm = perm.intern();
1113 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 } else if ("assign-permission".equals(name)) {
1116 String perm = parser.getAttributeValue(null, "name");
1117 if (perm == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001118 Slog.w(TAG, "<assign-permission> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 + parser.getPositionDescription());
1120 XmlUtils.skipCurrentTag(parser);
1121 continue;
1122 }
1123 String uidStr = parser.getAttributeValue(null, "uid");
1124 if (uidStr == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001125 Slog.w(TAG, "<assign-permission> without uid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001126 + parser.getPositionDescription());
1127 XmlUtils.skipCurrentTag(parser);
1128 continue;
1129 }
1130 int uid = Process.getUidForName(uidStr);
1131 if (uid < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001132 Slog.w(TAG, "<assign-permission> with unknown uid \""
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 + uidStr + "\" at "
1134 + parser.getPositionDescription());
1135 XmlUtils.skipCurrentTag(parser);
1136 continue;
1137 }
1138 perm = perm.intern();
1139 HashSet<String> perms = mSystemPermissions.get(uid);
1140 if (perms == null) {
1141 perms = new HashSet<String>();
1142 mSystemPermissions.put(uid, perms);
1143 }
1144 perms.add(perm);
1145 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 } else if ("library".equals(name)) {
1148 String lname = parser.getAttributeValue(null, "name");
1149 String lfile = parser.getAttributeValue(null, "file");
1150 if (lname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001151 Slog.w(TAG, "<library> without name at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 + parser.getPositionDescription());
1153 } else if (lfile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001154 Slog.w(TAG, "<library> without file at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 + parser.getPositionDescription());
1156 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001157 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -07001158 mSharedLibraries.put(lname, lfile);
1159 }
1160 XmlUtils.skipCurrentTag(parser);
1161 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001162
Dianne Hackborn49237342009-08-27 20:08:01 -07001163 } else if ("feature".equals(name)) {
1164 String fname = parser.getAttributeValue(null, "name");
1165 if (fname == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001166 Slog.w(TAG, "<feature> without name at "
Dianne Hackborn49237342009-08-27 20:08:01 -07001167 + parser.getPositionDescription());
1168 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07001169 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -07001170 FeatureInfo fi = new FeatureInfo();
1171 fi.name = fname;
1172 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 }
1174 XmlUtils.skipCurrentTag(parser);
1175 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 } else {
1178 XmlUtils.skipCurrentTag(parser);
1179 continue;
1180 }
1181
1182 }
1183 } catch (XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001184 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001186 Slog.w(TAG, "Got execption parsing permissions.", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
1188 }
1189
1190 void readPermission(XmlPullParser parser, String name)
1191 throws IOException, XmlPullParserException {
1192
1193 name = name.intern();
1194
1195 BasePermission bp = mSettings.mPermissions.get(name);
1196 if (bp == null) {
1197 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
1198 mSettings.mPermissions.put(name, bp);
1199 }
1200 int outerDepth = parser.getDepth();
1201 int type;
1202 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1203 && (type != XmlPullParser.END_TAG
1204 || parser.getDepth() > outerDepth)) {
1205 if (type == XmlPullParser.END_TAG
1206 || type == XmlPullParser.TEXT) {
1207 continue;
1208 }
1209
1210 String tagName = parser.getName();
1211 if ("group".equals(tagName)) {
1212 String gidStr = parser.getAttributeValue(null, "gid");
1213 if (gidStr != null) {
1214 int gid = Process.getGidForName(gidStr);
1215 bp.gids = appendInt(bp.gids, gid);
1216 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001217 Slog.w(TAG, "<group> without gid at "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 + parser.getPositionDescription());
1219 }
1220 }
1221 XmlUtils.skipCurrentTag(parser);
1222 }
1223 }
1224
1225 static int[] appendInt(int[] cur, int val) {
1226 if (cur == null) {
1227 return new int[] { val };
1228 }
1229 final int N = cur.length;
1230 for (int i=0; i<N; i++) {
1231 if (cur[i] == val) {
1232 return cur;
1233 }
1234 }
1235 int[] ret = new int[N+1];
1236 System.arraycopy(cur, 0, ret, 0, N);
1237 ret[N] = val;
1238 return ret;
1239 }
1240
1241 static int[] appendInts(int[] cur, int[] add) {
1242 if (add == null) return cur;
1243 if (cur == null) return add;
1244 final int N = add.length;
1245 for (int i=0; i<N; i++) {
1246 cur = appendInt(cur, add[i]);
1247 }
1248 return cur;
1249 }
1250
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001251 static int[] removeInt(int[] cur, int val) {
1252 if (cur == null) {
1253 return null;
1254 }
1255 final int N = cur.length;
1256 for (int i=0; i<N; i++) {
1257 if (cur[i] == val) {
1258 int[] ret = new int[N-1];
1259 if (i > 0) {
1260 System.arraycopy(cur, 0, ret, 0, i);
1261 }
1262 if (i < (N-1)) {
1263 System.arraycopy(cur, i, ret, i+1, N-i-1);
1264 }
1265 return ret;
1266 }
1267 }
1268 return cur;
1269 }
1270
1271 static int[] removeInts(int[] cur, int[] rem) {
1272 if (rem == null) return cur;
1273 if (cur == null) return cur;
1274 final int N = rem.length;
1275 for (int i=0; i<N; i++) {
1276 cur = removeInt(cur, rem[i]);
1277 }
1278 return cur;
1279 }
1280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001282 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1283 // The package has been uninstalled but has retained data and resources.
1284 return PackageParser.generatePackageInfo(p, null, flags);
1285 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 final PackageSetting ps = (PackageSetting)p.mExtras;
1287 if (ps == null) {
1288 return null;
1289 }
1290 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1291 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1292 }
1293
1294 public PackageInfo getPackageInfo(String packageName, int flags) {
1295 synchronized (mPackages) {
1296 PackageParser.Package p = mPackages.get(packageName);
1297 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001298 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 + ": " + p);
1300 if (p != null) {
1301 return generatePackageInfo(p, flags);
1302 }
1303 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1304 return generatePackageInfoFromSettingsLP(packageName, flags);
1305 }
1306 }
1307 return null;
1308 }
1309
Dianne Hackborn47096932010-02-11 15:57:09 -08001310 public String[] currentToCanonicalPackageNames(String[] names) {
1311 String[] out = new String[names.length];
1312 synchronized (mPackages) {
1313 for (int i=names.length-1; i>=0; i--) {
1314 PackageSetting ps = mSettings.mPackages.get(names[i]);
1315 out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
1316 }
1317 }
1318 return out;
1319 }
1320
1321 public String[] canonicalToCurrentPackageNames(String[] names) {
1322 String[] out = new String[names.length];
1323 synchronized (mPackages) {
1324 for (int i=names.length-1; i>=0; i--) {
1325 String cur = mSettings.mRenamedPackages.get(names[i]);
1326 out[i] = cur != null ? cur : names[i];
1327 }
1328 }
1329 return out;
1330 }
1331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 public int getPackageUid(String packageName) {
1333 synchronized (mPackages) {
1334 PackageParser.Package p = mPackages.get(packageName);
1335 if(p != null) {
1336 return p.applicationInfo.uid;
1337 }
1338 PackageSetting ps = mSettings.mPackages.get(packageName);
1339 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1340 return -1;
1341 }
1342 p = ps.pkg;
1343 return p != null ? p.applicationInfo.uid : -1;
1344 }
1345 }
1346
1347 public int[] getPackageGids(String packageName) {
1348 synchronized (mPackages) {
1349 PackageParser.Package p = mPackages.get(packageName);
1350 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001351 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 + ": " + p);
1353 if (p != null) {
1354 final PackageSetting ps = (PackageSetting)p.mExtras;
1355 final SharedUserSetting suid = ps.sharedUser;
1356 return suid != null ? suid.gids : ps.gids;
1357 }
1358 }
1359 // stupid thing to indicate an error.
1360 return new int[0];
1361 }
1362
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001363 static final PermissionInfo generatePermissionInfo(
1364 BasePermission bp, int flags) {
1365 if (bp.perm != null) {
1366 return PackageParser.generatePermissionInfo(bp.perm, flags);
1367 }
1368 PermissionInfo pi = new PermissionInfo();
1369 pi.name = bp.name;
1370 pi.packageName = bp.sourcePackage;
1371 pi.nonLocalizedLabel = bp.name;
1372 pi.protectionLevel = bp.protectionLevel;
1373 return pi;
1374 }
1375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 public PermissionInfo getPermissionInfo(String name, int flags) {
1377 synchronized (mPackages) {
1378 final BasePermission p = mSettings.mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001379 if (p != null) {
1380 return generatePermissionInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 }
1382 return null;
1383 }
1384 }
1385
1386 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1387 synchronized (mPackages) {
1388 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1389 for (BasePermission p : mSettings.mPermissions.values()) {
1390 if (group == null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001391 if (p.perm == null || p.perm.info.group == null) {
1392 out.add(generatePermissionInfo(p, flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 }
1394 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07001395 if (p.perm != null && group.equals(p.perm.info.group)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1397 }
1398 }
1399 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 if (out.size() > 0) {
1402 return out;
1403 }
1404 return mPermissionGroups.containsKey(group) ? out : null;
1405 }
1406 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1409 synchronized (mPackages) {
1410 return PackageParser.generatePermissionGroupInfo(
1411 mPermissionGroups.get(name), flags);
1412 }
1413 }
1414
1415 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1416 synchronized (mPackages) {
1417 final int N = mPermissionGroups.size();
1418 ArrayList<PermissionGroupInfo> out
1419 = new ArrayList<PermissionGroupInfo>(N);
1420 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1421 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1422 }
1423 return out;
1424 }
1425 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1428 PackageSetting ps = mSettings.mPackages.get(packageName);
1429 if(ps != null) {
1430 if(ps.pkg == null) {
1431 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1432 if(pInfo != null) {
1433 return pInfo.applicationInfo;
1434 }
1435 return null;
1436 }
1437 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1438 }
1439 return null;
1440 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1443 PackageSetting ps = mSettings.mPackages.get(packageName);
1444 if(ps != null) {
1445 if(ps.pkg == null) {
1446 ps.pkg = new PackageParser.Package(packageName);
1447 ps.pkg.applicationInfo.packageName = packageName;
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08001448 ps.pkg.applicationInfo.flags = ps.pkgFlags;
1449 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
1450 ps.pkg.applicationInfo.sourceDir = ps.codePathString;
1451 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 }
1453 return generatePackageInfo(ps.pkg, flags);
1454 }
1455 return null;
1456 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1459 synchronized (mPackages) {
1460 PackageParser.Package p = mPackages.get(packageName);
1461 if (Config.LOGV) Log.v(
1462 TAG, "getApplicationInfo " + packageName
1463 + ": " + p);
1464 if (p != null) {
1465 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001466 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468 if ("android".equals(packageName)||"system".equals(packageName)) {
1469 return mAndroidApplication;
1470 }
1471 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1472 return generateApplicationInfoFromSettingsLP(packageName, flags);
1473 }
1474 }
1475 return null;
1476 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001477
1478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1480 mContext.enforceCallingOrSelfPermission(
1481 android.Manifest.permission.CLEAR_APP_CACHE, null);
1482 // Queue up an async operation since clearing cache may take a little while.
1483 mHandler.post(new Runnable() {
1484 public void run() {
1485 mHandler.removeCallbacks(this);
1486 int retCode = -1;
1487 if (mInstaller != null) {
1488 retCode = mInstaller.freeCache(freeStorageSize);
1489 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001490 Slog.w(TAG, "Couldn't clear application caches");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 }
1492 } //end if mInstaller
1493 if (observer != null) {
1494 try {
1495 observer.onRemoveCompleted(null, (retCode >= 0));
1496 } catch (RemoteException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001497 Slog.w(TAG, "RemoveException when invoking call back");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 }
1499 }
1500 }
1501 });
1502 }
1503
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001504 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001505 mContext.enforceCallingOrSelfPermission(
1506 android.Manifest.permission.CLEAR_APP_CACHE, null);
1507 // Queue up an async operation since clearing cache may take a little while.
1508 mHandler.post(new Runnable() {
1509 public void run() {
1510 mHandler.removeCallbacks(this);
1511 int retCode = -1;
1512 if (mInstaller != null) {
1513 retCode = mInstaller.freeCache(freeStorageSize);
1514 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001515 Slog.w(TAG, "Couldn't clear application caches");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001516 }
1517 }
1518 if(pi != null) {
1519 try {
1520 // Callback via pending intent
1521 int code = (retCode >= 0) ? 1 : 0;
1522 pi.sendIntent(null, code, null,
1523 null, null);
1524 } catch (SendIntentException e1) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001525 Slog.i(TAG, "Failed to send pending intent");
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001526 }
1527 }
1528 }
1529 });
1530 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1533 synchronized (mPackages) {
1534 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001535
1536 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001538 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540 if (mResolveComponentName.equals(component)) {
1541 return mResolveActivity;
1542 }
1543 }
1544 return null;
1545 }
1546
1547 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1548 synchronized (mPackages) {
1549 PackageParser.Activity a = mReceivers.mActivities.get(component);
1550 if (Config.LOGV) Log.v(
1551 TAG, "getReceiverInfo " + component + ": " + a);
1552 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1553 return PackageParser.generateActivityInfo(a, flags);
1554 }
1555 }
1556 return null;
1557 }
1558
1559 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1560 synchronized (mPackages) {
1561 PackageParser.Service s = mServices.mServices.get(component);
1562 if (Config.LOGV) Log.v(
1563 TAG, "getServiceInfo " + component + ": " + s);
1564 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1565 return PackageParser.generateServiceInfo(s, flags);
1566 }
1567 }
1568 return null;
1569 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 public String[] getSystemSharedLibraryNames() {
1572 Set<String> libSet;
1573 synchronized (mPackages) {
1574 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001575 int size = libSet.size();
1576 if (size > 0) {
1577 String[] libs = new String[size];
1578 libSet.toArray(libs);
1579 return libs;
1580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001582 return null;
1583 }
1584
1585 public FeatureInfo[] getSystemAvailableFeatures() {
1586 Collection<FeatureInfo> featSet;
1587 synchronized (mPackages) {
1588 featSet = mAvailableFeatures.values();
1589 int size = featSet.size();
1590 if (size > 0) {
1591 FeatureInfo[] features = new FeatureInfo[size+1];
1592 featSet.toArray(features);
1593 FeatureInfo fi = new FeatureInfo();
1594 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1595 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1596 features[size] = fi;
1597 return features;
1598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 }
1600 return null;
1601 }
1602
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001603 public boolean hasSystemFeature(String name) {
1604 synchronized (mPackages) {
1605 return mAvailableFeatures.containsKey(name);
1606 }
1607 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 public int checkPermission(String permName, String pkgName) {
1610 synchronized (mPackages) {
1611 PackageParser.Package p = mPackages.get(pkgName);
1612 if (p != null && p.mExtras != null) {
1613 PackageSetting ps = (PackageSetting)p.mExtras;
1614 if (ps.sharedUser != null) {
1615 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1616 return PackageManager.PERMISSION_GRANTED;
1617 }
1618 } else if (ps.grantedPermissions.contains(permName)) {
1619 return PackageManager.PERMISSION_GRANTED;
1620 }
1621 }
1622 }
1623 return PackageManager.PERMISSION_DENIED;
1624 }
1625
1626 public int checkUidPermission(String permName, int uid) {
1627 synchronized (mPackages) {
1628 Object obj = mSettings.getUserIdLP(uid);
1629 if (obj != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001630 GrantedPermissions gp = (GrantedPermissions)obj;
1631 if (gp.grantedPermissions.contains(permName)) {
1632 return PackageManager.PERMISSION_GRANTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 }
1634 } else {
1635 HashSet<String> perms = mSystemPermissions.get(uid);
1636 if (perms != null && perms.contains(permName)) {
1637 return PackageManager.PERMISSION_GRANTED;
1638 }
1639 }
1640 }
1641 return PackageManager.PERMISSION_DENIED;
1642 }
1643
1644 private BasePermission findPermissionTreeLP(String permName) {
1645 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1646 if (permName.startsWith(bp.name) &&
1647 permName.length() > bp.name.length() &&
1648 permName.charAt(bp.name.length()) == '.') {
1649 return bp;
1650 }
1651 }
1652 return null;
1653 }
1654
1655 private BasePermission checkPermissionTreeLP(String permName) {
1656 if (permName != null) {
1657 BasePermission bp = findPermissionTreeLP(permName);
1658 if (bp != null) {
1659 if (bp.uid == Binder.getCallingUid()) {
1660 return bp;
1661 }
1662 throw new SecurityException("Calling uid "
1663 + Binder.getCallingUid()
1664 + " is not allowed to add to permission tree "
1665 + bp.name + " owned by uid " + bp.uid);
1666 }
1667 }
1668 throw new SecurityException("No permission tree found for " + permName);
1669 }
1670
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001671 static boolean compareStrings(CharSequence s1, CharSequence s2) {
1672 if (s1 == null) {
1673 return s2 == null;
1674 }
1675 if (s2 == null) {
1676 return false;
1677 }
1678 if (s1.getClass() != s2.getClass()) {
1679 return false;
1680 }
1681 return s1.equals(s2);
1682 }
1683
1684 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
1685 if (pi1.icon != pi2.icon) return false;
1686 if (pi1.protectionLevel != pi2.protectionLevel) return false;
1687 if (!compareStrings(pi1.name, pi2.name)) return false;
1688 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
1689 // We'll take care of setting this one.
1690 if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
1691 // These are not currently stored in settings.
1692 //if (!compareStrings(pi1.group, pi2.group)) return false;
1693 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
1694 //if (pi1.labelRes != pi2.labelRes) return false;
1695 //if (pi1.descriptionRes != pi2.descriptionRes) return false;
1696 return true;
1697 }
1698
1699 boolean addPermissionLocked(PermissionInfo info, boolean async) {
1700 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1701 throw new SecurityException("Label must be specified in permission");
1702 }
1703 BasePermission tree = checkPermissionTreeLP(info.name);
1704 BasePermission bp = mSettings.mPermissions.get(info.name);
1705 boolean added = bp == null;
1706 boolean changed = true;
1707 if (added) {
1708 bp = new BasePermission(info.name, tree.sourcePackage,
1709 BasePermission.TYPE_DYNAMIC);
1710 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1711 throw new SecurityException(
1712 "Not allowed to modify non-dynamic permission "
1713 + info.name);
1714 } else {
1715 if (bp.protectionLevel == info.protectionLevel
1716 && bp.perm.owner.equals(tree.perm.owner)
1717 && bp.uid == tree.uid
1718 && comparePermissionInfos(bp.perm.info, info)) {
1719 changed = false;
1720 }
1721 }
1722 bp.protectionLevel = info.protectionLevel;
1723 bp.perm = new PackageParser.Permission(tree.perm.owner,
1724 new PermissionInfo(info));
1725 bp.perm.info.packageName = tree.perm.info.packageName;
1726 bp.uid = tree.uid;
1727 if (added) {
1728 mSettings.mPermissions.put(info.name, bp);
1729 }
1730 if (changed) {
1731 if (!async) {
1732 mSettings.writeLP();
1733 } else {
1734 scheduleWriteSettingsLocked();
1735 }
1736 }
1737 return added;
1738 }
1739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 public boolean addPermission(PermissionInfo info) {
1741 synchronized (mPackages) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001742 return addPermissionLocked(info, false);
1743 }
1744 }
1745
1746 public boolean addPermissionAsync(PermissionInfo info) {
1747 synchronized (mPackages) {
1748 return addPermissionLocked(info, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 }
1750 }
1751
1752 public void removePermission(String name) {
1753 synchronized (mPackages) {
1754 checkPermissionTreeLP(name);
1755 BasePermission bp = mSettings.mPermissions.get(name);
1756 if (bp != null) {
1757 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1758 throw new SecurityException(
1759 "Not allowed to modify non-dynamic permission "
1760 + name);
1761 }
1762 mSettings.mPermissions.remove(name);
1763 mSettings.writeLP();
1764 }
1765 }
1766 }
1767
Dianne Hackborn854060af2009-07-09 18:14:31 -07001768 public boolean isProtectedBroadcast(String actionName) {
1769 synchronized (mPackages) {
1770 return mProtectedBroadcasts.contains(actionName);
1771 }
1772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 public int checkSignatures(String pkg1, String pkg2) {
1775 synchronized (mPackages) {
1776 PackageParser.Package p1 = mPackages.get(pkg1);
1777 PackageParser.Package p2 = mPackages.get(pkg2);
1778 if (p1 == null || p1.mExtras == null
1779 || p2 == null || p2.mExtras == null) {
1780 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1781 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001782 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 }
1784 }
1785
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001786 public int checkUidSignatures(int uid1, int uid2) {
1787 synchronized (mPackages) {
1788 Signature[] s1;
1789 Signature[] s2;
1790 Object obj = mSettings.getUserIdLP(uid1);
1791 if (obj != null) {
1792 if (obj instanceof SharedUserSetting) {
1793 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1794 } else if (obj instanceof PackageSetting) {
1795 s1 = ((PackageSetting)obj).signatures.mSignatures;
1796 } else {
1797 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1798 }
1799 } else {
1800 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1801 }
1802 obj = mSettings.getUserIdLP(uid2);
1803 if (obj != null) {
1804 if (obj instanceof SharedUserSetting) {
1805 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1806 } else if (obj instanceof PackageSetting) {
1807 s2 = ((PackageSetting)obj).signatures.mSignatures;
1808 } else {
1809 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1810 }
1811 } else {
1812 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1813 }
1814 return checkSignaturesLP(s1, s2);
1815 }
1816 }
1817
1818 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1819 if (s1 == null) {
1820 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1822 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1823 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001824 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1826 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001827 HashSet<Signature> set1 = new HashSet<Signature>();
1828 for (Signature sig : s1) {
1829 set1.add(sig);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07001831 HashSet<Signature> set2 = new HashSet<Signature>();
1832 for (Signature sig : s2) {
1833 set2.add(sig);
1834 }
1835 // Make sure s2 contains all signatures in s1.
1836 if (set1.equals(set2)) {
1837 return PackageManager.SIGNATURE_MATCH;
1838 }
1839 return PackageManager.SIGNATURE_NO_MATCH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841
1842 public String[] getPackagesForUid(int uid) {
1843 synchronized (mPackages) {
1844 Object obj = mSettings.getUserIdLP(uid);
1845 if (obj instanceof SharedUserSetting) {
1846 SharedUserSetting sus = (SharedUserSetting)obj;
1847 final int N = sus.packages.size();
1848 String[] res = new String[N];
1849 Iterator<PackageSetting> it = sus.packages.iterator();
1850 int i=0;
1851 while (it.hasNext()) {
1852 res[i++] = it.next().name;
1853 }
1854 return res;
1855 } else if (obj instanceof PackageSetting) {
1856 PackageSetting ps = (PackageSetting)obj;
1857 return new String[] { ps.name };
1858 }
1859 }
1860 return null;
1861 }
1862
1863 public String getNameForUid(int uid) {
1864 synchronized (mPackages) {
1865 Object obj = mSettings.getUserIdLP(uid);
1866 if (obj instanceof SharedUserSetting) {
1867 SharedUserSetting sus = (SharedUserSetting)obj;
1868 return sus.name + ":" + sus.userId;
1869 } else if (obj instanceof PackageSetting) {
1870 PackageSetting ps = (PackageSetting)obj;
1871 return ps.name;
1872 }
1873 }
1874 return null;
1875 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 public int getUidForSharedUser(String sharedUserName) {
1878 if(sharedUserName == null) {
1879 return -1;
1880 }
1881 synchronized (mPackages) {
1882 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1883 if(suid == null) {
1884 return -1;
1885 }
1886 return suid.userId;
1887 }
1888 }
1889
1890 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1891 int flags) {
1892 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001893 return chooseBestActivity(intent, resolvedType, flags, query);
1894 }
1895
Mihai Predaeae850c2009-05-13 10:13:48 +02001896 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1897 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 if (query != null) {
1899 final int N = query.size();
1900 if (N == 1) {
1901 return query.get(0);
1902 } else if (N > 1) {
1903 // If there is more than one activity with the same priority,
1904 // then let the user decide between them.
1905 ResolveInfo r0 = query.get(0);
1906 ResolveInfo r1 = query.get(1);
1907 if (false) {
1908 System.out.println(r0.activityInfo.name +
1909 "=" + r0.priority + " vs " +
1910 r1.activityInfo.name +
1911 "=" + r1.priority);
1912 }
1913 // If the first activity has a higher priority, or a different
1914 // default, then it is always desireable to pick it.
1915 if (r0.priority != r1.priority
1916 || r0.preferredOrder != r1.preferredOrder
1917 || r0.isDefault != r1.isDefault) {
1918 return query.get(0);
1919 }
1920 // If we have saved a preference for a preferred activity for
1921 // this Intent, use that.
1922 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1923 flags, query, r0.priority);
1924 if (ri != null) {
1925 return ri;
1926 }
1927 return mResolveInfo;
1928 }
1929 }
1930 return null;
1931 }
1932
1933 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1934 int flags, List<ResolveInfo> query, int priority) {
1935 synchronized (mPackages) {
1936 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1937 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001938 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1940 if (prefs != null && prefs.size() > 0) {
1941 // First figure out how good the original match set is.
1942 // We will only allow preferred activities that came
1943 // from the same match quality.
1944 int match = 0;
1945 final int N = query.size();
1946 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1947 for (int j=0; j<N; j++) {
1948 ResolveInfo ri = query.get(j);
1949 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1950 + ": 0x" + Integer.toHexString(match));
1951 if (ri.match > match) match = ri.match;
1952 }
1953 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1954 + Integer.toHexString(match));
1955 match &= IntentFilter.MATCH_CATEGORY_MASK;
1956 final int M = prefs.size();
1957 for (int i=0; i<M; i++) {
1958 PreferredActivity pa = prefs.get(i);
1959 if (pa.mMatch != match) {
1960 continue;
1961 }
1962 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1963 if (DEBUG_PREFERRED) {
1964 Log.v(TAG, "Got preferred activity:");
1965 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1966 }
1967 if (ai != null) {
1968 for (int j=0; j<N; j++) {
1969 ResolveInfo ri = query.get(j);
1970 if (!ri.activityInfo.applicationInfo.packageName
1971 .equals(ai.applicationInfo.packageName)) {
1972 continue;
1973 }
1974 if (!ri.activityInfo.name.equals(ai.name)) {
1975 continue;
1976 }
1977
1978 // Okay we found a previously set preferred app.
1979 // If the result set is different from when this
1980 // was created, we need to clear it and re-ask the
1981 // user their preference.
1982 if (!pa.sameSet(query, priority)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08001983 Slog.i(TAG, "Result set changed, dropping preferred activity for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 + intent + " type " + resolvedType);
1985 mSettings.mPreferredActivities.removeFilter(pa);
1986 return null;
1987 }
1988
1989 // Yay!
1990 return ri;
1991 }
1992 }
1993 }
1994 }
1995 }
1996 return null;
1997 }
1998
1999 public List<ResolveInfo> queryIntentActivities(Intent intent,
2000 String resolvedType, int flags) {
2001 ComponentName comp = intent.getComponent();
2002 if (comp != null) {
2003 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2004 ActivityInfo ai = getActivityInfo(comp, flags);
2005 if (ai != null) {
2006 ResolveInfo ri = new ResolveInfo();
2007 ri.activityInfo = ai;
2008 list.add(ri);
2009 }
2010 return list;
2011 }
2012
2013 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002014 String pkgName = intent.getPackage();
2015 if (pkgName == null) {
2016 return (List<ResolveInfo>)mActivities.queryIntent(intent,
2017 resolvedType, flags);
2018 }
2019 PackageParser.Package pkg = mPackages.get(pkgName);
2020 if (pkg != null) {
2021 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
2022 resolvedType, flags, pkg.activities);
2023 }
2024 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 }
2026 }
2027
2028 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
2029 Intent[] specifics, String[] specificTypes, Intent intent,
2030 String resolvedType, int flags) {
2031 final String resultsAction = intent.getAction();
2032
2033 List<ResolveInfo> results = queryIntentActivities(
2034 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
2035 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
2036
2037 int specificsPos = 0;
2038 int N;
2039
2040 // todo: note that the algorithm used here is O(N^2). This
2041 // isn't a problem in our current environment, but if we start running
2042 // into situations where we have more than 5 or 10 matches then this
2043 // should probably be changed to something smarter...
2044
2045 // First we go through and resolve each of the specific items
2046 // that were supplied, taking care of removing any corresponding
2047 // duplicate items in the generic resolve list.
2048 if (specifics != null) {
2049 for (int i=0; i<specifics.length; i++) {
2050 final Intent sintent = specifics[i];
2051 if (sintent == null) {
2052 continue;
2053 }
2054
2055 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
2056 String action = sintent.getAction();
2057 if (resultsAction != null && resultsAction.equals(action)) {
2058 // If this action was explicitly requested, then don't
2059 // remove things that have it.
2060 action = null;
2061 }
2062 ComponentName comp = sintent.getComponent();
2063 ResolveInfo ri = null;
2064 ActivityInfo ai = null;
2065 if (comp == null) {
2066 ri = resolveIntent(
2067 sintent,
2068 specificTypes != null ? specificTypes[i] : null,
2069 flags);
2070 if (ri == null) {
2071 continue;
2072 }
2073 if (ri == mResolveInfo) {
2074 // ACK! Must do something better with this.
2075 }
2076 ai = ri.activityInfo;
2077 comp = new ComponentName(ai.applicationInfo.packageName,
2078 ai.name);
2079 } else {
2080 ai = getActivityInfo(comp, flags);
2081 if (ai == null) {
2082 continue;
2083 }
2084 }
2085
2086 // Look for any generic query activities that are duplicates
2087 // of this specific one, and remove them from the results.
2088 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
2089 N = results.size();
2090 int j;
2091 for (j=specificsPos; j<N; j++) {
2092 ResolveInfo sri = results.get(j);
2093 if ((sri.activityInfo.name.equals(comp.getClassName())
2094 && sri.activityInfo.applicationInfo.packageName.equals(
2095 comp.getPackageName()))
2096 || (action != null && sri.filter.matchAction(action))) {
2097 results.remove(j);
2098 if (Config.LOGV) Log.v(
2099 TAG, "Removing duplicate item from " + j
2100 + " due to specific " + specificsPos);
2101 if (ri == null) {
2102 ri = sri;
2103 }
2104 j--;
2105 N--;
2106 }
2107 }
2108
2109 // Add this specific item to its proper place.
2110 if (ri == null) {
2111 ri = new ResolveInfo();
2112 ri.activityInfo = ai;
2113 }
2114 results.add(specificsPos, ri);
2115 ri.specificIndex = i;
2116 specificsPos++;
2117 }
2118 }
2119
2120 // Now we go through the remaining generic results and remove any
2121 // duplicate actions that are found here.
2122 N = results.size();
2123 for (int i=specificsPos; i<N-1; i++) {
2124 final ResolveInfo rii = results.get(i);
2125 if (rii.filter == null) {
2126 continue;
2127 }
2128
2129 // Iterate over all of the actions of this result's intent
2130 // filter... typically this should be just one.
2131 final Iterator<String> it = rii.filter.actionsIterator();
2132 if (it == null) {
2133 continue;
2134 }
2135 while (it.hasNext()) {
2136 final String action = it.next();
2137 if (resultsAction != null && resultsAction.equals(action)) {
2138 // If this action was explicitly requested, then don't
2139 // remove things that have it.
2140 continue;
2141 }
2142 for (int j=i+1; j<N; j++) {
2143 final ResolveInfo rij = results.get(j);
2144 if (rij.filter != null && rij.filter.hasAction(action)) {
2145 results.remove(j);
2146 if (Config.LOGV) Log.v(
2147 TAG, "Removing duplicate item from " + j
2148 + " due to action " + action + " at " + i);
2149 j--;
2150 N--;
2151 }
2152 }
2153 }
2154
2155 // If the caller didn't request filter information, drop it now
2156 // so we don't have to marshall/unmarshall it.
2157 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2158 rii.filter = null;
2159 }
2160 }
2161
2162 // Filter out the caller activity if so requested.
2163 if (caller != null) {
2164 N = results.size();
2165 for (int i=0; i<N; i++) {
2166 ActivityInfo ainfo = results.get(i).activityInfo;
2167 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
2168 && caller.getClassName().equals(ainfo.name)) {
2169 results.remove(i);
2170 break;
2171 }
2172 }
2173 }
2174
2175 // If the caller didn't request filter information,
2176 // drop them now so we don't have to
2177 // marshall/unmarshall it.
2178 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
2179 N = results.size();
2180 for (int i=0; i<N; i++) {
2181 results.get(i).filter = null;
2182 }
2183 }
2184
2185 if (Config.LOGV) Log.v(TAG, "Result: " + results);
2186 return results;
2187 }
2188
2189 public List<ResolveInfo> queryIntentReceivers(Intent intent,
2190 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002191 ComponentName comp = intent.getComponent();
2192 if (comp != null) {
2193 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2194 ActivityInfo ai = getReceiverInfo(comp, flags);
2195 if (ai != null) {
2196 ResolveInfo ri = new ResolveInfo();
2197 ri.activityInfo = ai;
2198 list.add(ri);
2199 }
2200 return list;
2201 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002204 String pkgName = intent.getPackage();
2205 if (pkgName == null) {
2206 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
2207 resolvedType, flags);
2208 }
2209 PackageParser.Package pkg = mPackages.get(pkgName);
2210 if (pkg != null) {
2211 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
2212 resolvedType, flags, pkg.receivers);
2213 }
2214 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 }
2216 }
2217
2218 public ResolveInfo resolveService(Intent intent, String resolvedType,
2219 int flags) {
2220 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
2221 flags);
2222 if (query != null) {
2223 if (query.size() >= 1) {
2224 // If there is more than one service with the same priority,
2225 // just arbitrarily pick the first one.
2226 return query.get(0);
2227 }
2228 }
2229 return null;
2230 }
2231
2232 public List<ResolveInfo> queryIntentServices(Intent intent,
2233 String resolvedType, int flags) {
2234 ComponentName comp = intent.getComponent();
2235 if (comp != null) {
2236 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
2237 ServiceInfo si = getServiceInfo(comp, flags);
2238 if (si != null) {
2239 ResolveInfo ri = new ResolveInfo();
2240 ri.serviceInfo = si;
2241 list.add(ri);
2242 }
2243 return list;
2244 }
2245
2246 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07002247 String pkgName = intent.getPackage();
2248 if (pkgName == null) {
2249 return (List<ResolveInfo>)mServices.queryIntent(intent,
2250 resolvedType, flags);
2251 }
2252 PackageParser.Package pkg = mPackages.get(pkgName);
2253 if (pkg != null) {
2254 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
2255 resolvedType, flags, pkg.services);
2256 }
2257 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 }
2259 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002261 public List<PackageInfo> getInstalledPackages(int flags) {
2262 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
2263
2264 synchronized (mPackages) {
2265 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2266 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2267 while (i.hasNext()) {
2268 final PackageSetting ps = i.next();
2269 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
2270 if(psPkg != null) {
2271 finalList.add(psPkg);
2272 }
2273 }
2274 }
2275 else {
2276 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2277 while (i.hasNext()) {
2278 final PackageParser.Package p = i.next();
2279 if (p.applicationInfo != null) {
2280 PackageInfo pi = generatePackageInfo(p, flags);
2281 if(pi != null) {
2282 finalList.add(pi);
2283 }
2284 }
2285 }
2286 }
2287 }
2288 return finalList;
2289 }
2290
2291 public List<ApplicationInfo> getInstalledApplications(int flags) {
2292 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2293 synchronized(mPackages) {
2294 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
2295 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
2296 while (i.hasNext()) {
2297 final PackageSetting ps = i.next();
2298 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
2299 if(ai != null) {
2300 finalList.add(ai);
2301 }
2302 }
2303 }
2304 else {
2305 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2306 while (i.hasNext()) {
2307 final PackageParser.Package p = i.next();
2308 if (p.applicationInfo != null) {
2309 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
2310 if(ai != null) {
2311 finalList.add(ai);
2312 }
2313 }
2314 }
2315 }
2316 }
2317 return finalList;
2318 }
2319
2320 public List<ApplicationInfo> getPersistentApplications(int flags) {
2321 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2322
2323 synchronized (mPackages) {
2324 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2325 while (i.hasNext()) {
2326 PackageParser.Package p = i.next();
2327 if (p.applicationInfo != null
2328 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
2329 && (!mSafeMode || (p.applicationInfo.flags
2330 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2331 finalList.add(p.applicationInfo);
2332 }
2333 }
2334 }
2335
2336 return finalList;
2337 }
2338
2339 public ProviderInfo resolveContentProvider(String name, int flags) {
2340 synchronized (mPackages) {
2341 final PackageParser.Provider provider = mProviders.get(name);
2342 return provider != null
2343 && mSettings.isEnabledLP(provider.info, flags)
2344 && (!mSafeMode || (provider.info.applicationInfo.flags
2345 &ApplicationInfo.FLAG_SYSTEM) != 0)
2346 ? PackageParser.generateProviderInfo(provider, flags)
2347 : null;
2348 }
2349 }
2350
Fred Quintana718d8a22009-04-29 17:53:20 -07002351 /**
2352 * @deprecated
2353 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 public void querySyncProviders(List outNames, List outInfo) {
2355 synchronized (mPackages) {
2356 Iterator<Map.Entry<String, PackageParser.Provider>> i
2357 = mProviders.entrySet().iterator();
2358
2359 while (i.hasNext()) {
2360 Map.Entry<String, PackageParser.Provider> entry = i.next();
2361 PackageParser.Provider p = entry.getValue();
2362
2363 if (p.syncable
2364 && (!mSafeMode || (p.info.applicationInfo.flags
2365 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2366 outNames.add(entry.getKey());
2367 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2368 }
2369 }
2370 }
2371 }
2372
2373 public List<ProviderInfo> queryContentProviders(String processName,
2374 int uid, int flags) {
2375 ArrayList<ProviderInfo> finalList = null;
2376
2377 synchronized (mPackages) {
2378 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2379 while (i.hasNext()) {
2380 PackageParser.Provider p = i.next();
2381 if (p.info.authority != null
2382 && (processName == null ||
2383 (p.info.processName.equals(processName)
2384 && p.info.applicationInfo.uid == uid))
2385 && mSettings.isEnabledLP(p.info, flags)
2386 && (!mSafeMode || (p.info.applicationInfo.flags
2387 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2388 if (finalList == null) {
2389 finalList = new ArrayList<ProviderInfo>(3);
2390 }
2391 finalList.add(PackageParser.generateProviderInfo(p,
2392 flags));
2393 }
2394 }
2395 }
2396
2397 if (finalList != null) {
2398 Collections.sort(finalList, mProviderInitOrderSorter);
2399 }
2400
2401 return finalList;
2402 }
2403
2404 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2405 int flags) {
2406 synchronized (mPackages) {
2407 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2408 return PackageParser.generateInstrumentationInfo(i, flags);
2409 }
2410 }
2411
2412 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2413 int flags) {
2414 ArrayList<InstrumentationInfo> finalList =
2415 new ArrayList<InstrumentationInfo>();
2416
2417 synchronized (mPackages) {
2418 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2419 while (i.hasNext()) {
2420 PackageParser.Instrumentation p = i.next();
2421 if (targetPackage == null
2422 || targetPackage.equals(p.info.targetPackage)) {
2423 finalList.add(PackageParser.generateInstrumentationInfo(p,
2424 flags));
2425 }
2426 }
2427 }
2428
2429 return finalList;
2430 }
2431
2432 private void scanDirLI(File dir, int flags, int scanMode) {
2433 Log.d(TAG, "Scanning app dir " + dir);
2434
2435 String[] files = dir.list();
2436
2437 int i;
2438 for (i=0; i<files.length; i++) {
2439 File file = new File(dir, files[i]);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002440 if (!isPackageFilename(files[i])) {
2441 // Ignore entries which are not apk's
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002442 continue;
2443 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002444 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002446 // Don't mess around with apps in system partition.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08002447 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
2448 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002449 // Delete the apk
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002450 Slog.w(TAG, "Cleaning up failed install of " + file);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002451 file.delete();
2452 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 }
2454 }
2455
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002456 private static File getSettingsProblemFile() {
2457 File dataDir = Environment.getDataDirectory();
2458 File systemDir = new File(dataDir, "system");
2459 File fname = new File(systemDir, "uiderrors.txt");
2460 return fname;
2461 }
2462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 private static void reportSettingsProblem(int priority, String msg) {
2464 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002465 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 FileOutputStream out = new FileOutputStream(fname, true);
2467 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002468 SimpleDateFormat formatter = new SimpleDateFormat();
2469 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2470 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 pw.close();
2472 FileUtils.setPermissions(
2473 fname.toString(),
2474 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2475 -1, -1);
2476 } catch (java.io.IOException e) {
2477 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002478 Slog.println(priority, TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 }
2480
2481 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2482 PackageParser.Package pkg, File srcFile, int parseFlags) {
2483 if (GET_CERTIFICATES) {
2484 if (ps == null || !ps.codePath.equals(srcFile)
2485 || ps.getTimeStamp() != srcFile.lastModified()) {
2486 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2487 if (!pp.collectCertificates(pkg, parseFlags)) {
2488 mLastScanError = pp.getParseError();
2489 return false;
2490 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002491 } else {
2492 // Lets implicitly assign existing certificates.
2493 pkg.mSignatures = ps.signatures.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 }
2495 }
2496 return true;
2497 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 /*
2500 * Scan a package and return the newly parsed package.
2501 * Returns null in case of errors and the error code is stored in mLastScanError
2502 */
2503 private PackageParser.Package scanPackageLI(File scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002504 int parseFlags, int scanMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002506 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002508 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002511 scanPath, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 if (pkg == null) {
2513 mLastScanError = pp.getParseError();
2514 return null;
2515 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002516 PackageSetting ps = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 PackageSetting updatedPkg;
2518 synchronized (mPackages) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002519 // Look to see if we already know about this package.
2520 String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002521 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002522 // This package has been renamed to its original name. Let's
2523 // use that.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002524 ps = mSettings.peekPackageLP(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002525 }
2526 // If there was no original package, see one for the real package name.
2527 if (ps == null) {
2528 ps = mSettings.peekPackageLP(pkg.packageName);
2529 }
2530 // Check to see if this package could be hiding/updating a system
2531 // package. Must look for it either under the original or real
2532 // package name depending on our state.
2533 updatedPkg = mSettings.mDisabledSysPackages.get(
2534 ps != null ? ps.name : pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002535 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002536 // First check if this is a system package that may involve an update
2537 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2538 if (!ps.codePath.equals(scanFile)) {
2539 // The path has changed from what was last scanned... check the
2540 // version of the new path against what we have stored to determine
2541 // what to do.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002542 if (pkg.mVersionCode < ps.versionCode) {
2543 // The system package has been updated and the code path does not match
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002544 // Ignore entry. Skip it.
2545 Log.i(TAG, "Package " + ps.name + " at " + scanFile
2546 + "ignored: updated version " + ps.versionCode
2547 + " better than this " + pkg.mVersionCode);
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002548 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2549 return null;
2550 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002551 // The current app on the system partion is better than
2552 // what we have updated to on the data partition; switch
2553 // back to the system partition version.
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002554 // At this point, its safely assumed that package installation for
2555 // apps in system partition will go through. If not there won't be a working
2556 // version of the app
2557 synchronized (mPackages) {
2558 // Just remove the loaded entries from package lists.
2559 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002560 }
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002561 Slog.w(TAG, "Package " + ps.name + " at " + scanFile
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002562 + "reverting from " + ps.codePathString
2563 + ": new version " + pkg.mVersionCode
2564 + " better than installed " + ps.versionCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002565 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2566 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002567 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 }
2570 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002571 if (updatedPkg != null) {
2572 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2573 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2574 }
2575 // Verify certificates against what was last scanned
2576 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002577 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002578 return null;
2579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 // The apk is forward locked (not public) if its code and resources
2581 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002582 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002584 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002585 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002586
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002587 String codePath = null;
2588 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002589 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2590 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002591 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002592 } else {
2593 // Should not happen at all. Just log an error.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002594 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002595 }
2596 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002597 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002598 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002599 codePath = pkg.mScanPath;
2600 // Set application objects path explicitly.
2601 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002602 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002603 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 }
2605
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002606 private static void setApplicationInfoPaths(PackageParser.Package pkg,
2607 String destCodePath, String destResPath) {
2608 pkg.mPath = pkg.mScanPath = destCodePath;
2609 pkg.applicationInfo.sourceDir = destCodePath;
2610 pkg.applicationInfo.publicSourceDir = destResPath;
2611 }
2612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 private static String fixProcessName(String defProcessName,
2614 String processName, int uid) {
2615 if (processName == null) {
2616 return defProcessName;
2617 }
2618 return processName;
2619 }
2620
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002621 private boolean verifySignaturesLP(PackageSetting pkgSetting,
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002622 PackageParser.Package pkg) {
2623 if (pkgSetting.signatures.mSignatures != null) {
2624 // Already existing package. Make sure signatures match
2625 if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
2626 PackageManager.SIGNATURE_MATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002627 Slog.e(TAG, "Package " + pkg.packageName
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002628 + " signatures do not match the previously installed version; ignoring!");
2629 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 return false;
2631 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002632 }
2633 // Check for shared user signatures
2634 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
2635 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
2636 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
2637 Slog.e(TAG, "Package " + pkg.packageName
2638 + " has no signatures that match those in shared user "
2639 + pkgSetting.sharedUser.name + "; ignoring!");
2640 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2641 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 }
2644 return true;
2645 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002646
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002647 public boolean performDexOpt(String packageName) {
2648 if (!mNoDexOpt) {
2649 return false;
2650 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002651
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002652 PackageParser.Package p;
2653 synchronized (mPackages) {
2654 p = mPackages.get(packageName);
2655 if (p == null || p.mDidDexOpt) {
2656 return false;
2657 }
2658 }
2659 synchronized (mInstallLock) {
2660 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2661 }
2662 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002663
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002664 static final int DEX_OPT_SKIPPED = 0;
2665 static final int DEX_OPT_PERFORMED = 1;
2666 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002667
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002668 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2669 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002670 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002671 String path = pkg.mScanPath;
2672 int ret = 0;
2673 try {
2674 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002675 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002676 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002677 pkg.mDidDexOpt = true;
2678 performed = true;
2679 }
2680 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002681 Slog.w(TAG, "Apk not found for dexopt: " + path);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002682 ret = -1;
2683 } catch (IOException e) {
Suchi Amalapurapu73dafa12010-04-01 16:31:31 -07002684 Slog.w(TAG, "IOException reading apk: " + path, e);
2685 ret = -1;
2686 } catch (dalvik.system.StaleDexCacheError e) {
2687 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
2688 ret = -1;
2689 } catch (Exception e) {
2690 Slog.w(TAG, "Exception when doing dexopt : ", e);
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002691 ret = -1;
2692 }
2693 if (ret < 0) {
2694 //error from installer
2695 return DEX_OPT_FAILED;
2696 }
2697 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002698
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002699 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2700 }
2701
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002702 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2703 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002704 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002705 + " to " + newPkg.packageName
2706 + ": old package not in system partition");
2707 return false;
2708 } else if (mPackages.get(oldPkg.name) != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002709 Slog.w(TAG, "Unable to update from " + oldPkg.name
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002710 + " to " + newPkg.packageName
2711 + ": old package still exists");
2712 return false;
2713 }
2714 return true;
2715 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002716
2717 private File getDataPathForPackage(PackageParser.Package pkg) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07002718 return new File(mAppDataDir, pkg.packageName);
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08002719 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002720
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002721 private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
2722 int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002723 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002724 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2725 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002726 // Bail out. The resource and code paths haven't been set.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002727 Slog.w(TAG, " Code and resource paths haven't been set correctly");
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002728 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2729 return null;
2730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 mScanningPath = scanFile;
2732 if (pkg == null) {
2733 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2734 return null;
2735 }
2736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2738 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2739 }
2740
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002741 if (pkg.packageName.equals("android")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 synchronized (mPackages) {
2743 if (mAndroidApplication != null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002744 Slog.w(TAG, "*************************************************");
2745 Slog.w(TAG, "Core android package being redefined. Skipping.");
2746 Slog.w(TAG, " file=" + mScanningPath);
2747 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2749 return null;
2750 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 // Set up information for our fall-back user intent resolution
2753 // activity.
2754 mPlatformPackage = pkg;
2755 pkg.mVersionCode = mSdkVersion;
2756 mAndroidApplication = pkg.applicationInfo;
2757 mResolveActivity.applicationInfo = mAndroidApplication;
2758 mResolveActivity.name = ResolverActivity.class.getName();
2759 mResolveActivity.packageName = mAndroidApplication.packageName;
2760 mResolveActivity.processName = mAndroidApplication.processName;
2761 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2762 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2763 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2764 mResolveActivity.exported = true;
2765 mResolveActivity.enabled = true;
2766 mResolveInfo.activityInfo = mResolveActivity;
2767 mResolveInfo.priority = 0;
2768 mResolveInfo.preferredOrder = 0;
2769 mResolveInfo.match = 0;
2770 mResolveComponentName = new ComponentName(
2771 mAndroidApplication.packageName, mResolveActivity.name);
2772 }
2773 }
2774
2775 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002776 TAG, "Scanning package " + pkg.packageName);
2777 if (mPackages.containsKey(pkg.packageName)
2778 || mSharedLibraries.containsKey(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002779 Slog.w(TAG, "*************************************************");
2780 Slog.w(TAG, "Application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 + " already installed. Skipping duplicate.");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002782 Slog.w(TAG, "*************************************************");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2784 return null;
2785 }
2786
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002787 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002788 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2789 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 SharedUserSetting suid = null;
2792 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002793
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002794 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2795 // Only system apps can use these features.
Dianne Hackbornc1552392010-03-03 16:19:01 -08002796 pkg.mOriginalPackages = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002797 pkg.mRealPackage = null;
2798 pkg.mAdoptPermissions = null;
2799 }
2800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 synchronized (mPackages) {
2802 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002803 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2804 if (mTmpSharedLibraries == null ||
2805 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2806 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2807 }
2808 int num = 0;
2809 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2810 for (int i=0; i<N; i++) {
2811 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002813 Slog.e(TAG, "Package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002814 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002815 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2817 return null;
2818 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002819 mTmpSharedLibraries[num] = file;
2820 num++;
2821 }
2822 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2823 for (int i=0; i<N; i++) {
2824 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2825 if (file == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002826 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07002827 + " desires unavailable shared library "
2828 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2829 } else {
2830 mTmpSharedLibraries[num] = file;
2831 num++;
2832 }
2833 }
2834 if (num > 0) {
2835 pkg.usesLibraryFiles = new String[num];
2836 System.arraycopy(mTmpSharedLibraries, 0,
2837 pkg.usesLibraryFiles, 0, num);
2838 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002839
Dianne Hackborn49237342009-08-27 20:08:01 -07002840 if (pkg.reqFeatures != null) {
2841 N = pkg.reqFeatures.size();
2842 for (int i=0; i<N; i++) {
2843 FeatureInfo fi = pkg.reqFeatures.get(i);
2844 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2845 // Don't care.
2846 continue;
2847 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002848
Dianne Hackborn49237342009-08-27 20:08:01 -07002849 if (fi.name != null) {
2850 if (mAvailableFeatures.get(fi.name) == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002851 Slog.e(TAG, "Package " + pkg.packageName
Dianne Hackborn49237342009-08-27 20:08:01 -07002852 + " requires unavailable feature "
2853 + fi.name + "; failing!");
2854 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2855 return null;
2856 }
2857 }
2858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002859 }
2860 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 if (pkg.mSharedUserId != null) {
2863 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2864 pkg.applicationInfo.flags, true);
2865 if (suid == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002866 Slog.w(TAG, "Creating application package " + pkg.packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 + " for shared user failed");
2868 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2869 return null;
2870 }
2871 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2872 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2873 + suid.userId + "): packages=" + suid.packages);
2874 }
2875 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002876
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002877 if (false) {
Dianne Hackbornc1552392010-03-03 16:19:01 -08002878 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002879 Log.w(TAG, "WAITING FOR DEBUGGER");
2880 Debug.waitForDebugger();
Dianne Hackbornc1552392010-03-03 16:19:01 -08002881 Log.i(TAG, "Package " + pkg.packageName + " from original packages"
2882 + pkg.mOriginalPackages);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002883 }
2884 }
2885
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002886 // Check if we are renaming from an original package name.
2887 PackageSetting origPackage = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002888 String realName = null;
Dianne Hackbornc1552392010-03-03 16:19:01 -08002889 if (pkg.mOriginalPackages != null) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002890 // This package may need to be renamed to a previously
2891 // installed name. Let's check on that...
2892 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
Dianne Hackbornc1552392010-03-03 16:19:01 -08002893 if (pkg.mOriginalPackages.contains(renamed)) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002894 // This package had originally been installed as the
2895 // original name, and we have already taken care of
2896 // transitioning to the new one. Just update the new
2897 // one to continue using the old name.
2898 realName = pkg.mRealPackage;
2899 if (!pkg.packageName.equals(renamed)) {
2900 // Callers into this function may have already taken
2901 // care of renaming the package; only do it here if
2902 // it is not already done.
2903 pkg.setPackageName(renamed);
2904 }
2905
Dianne Hackbornc1552392010-03-03 16:19:01 -08002906 } else {
2907 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
2908 if ((origPackage=mSettings.peekPackageLP(
2909 pkg.mOriginalPackages.get(i))) != null) {
2910 // We do have the package already installed under its
2911 // original name... should we use it?
2912 if (!verifyPackageUpdate(origPackage, pkg)) {
2913 // New package is not compatible with original.
2914 origPackage = null;
2915 continue;
2916 } else if (origPackage.sharedUser != null) {
2917 // Make sure uid is compatible between packages.
2918 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002919 Slog.w(TAG, "Unable to migrate data from " + origPackage.name
Dianne Hackbornc1552392010-03-03 16:19:01 -08002920 + " to " + pkg.packageName + ": old uid "
2921 + origPackage.sharedUser.name
2922 + " differs from " + pkg.mSharedUserId);
2923 origPackage = null;
2924 continue;
2925 }
2926 } else {
2927 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
2928 + pkg.packageName + " to old name " + origPackage.name);
2929 }
2930 break;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002931 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002932 }
2933 }
2934 }
2935
2936 if (mTransferedPackages.contains(pkg.packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002937 Slog.w(TAG, "Package " + pkg.packageName
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002938 + " was transferred to another, but its .apk remains");
2939 }
2940
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002941 // Just create the setting, don't add it yet. For already existing packages
2942 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002943 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 destResourceFile, pkg.applicationInfo.flags, true, false);
2945 if (pkgSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08002946 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2948 return null;
2949 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08002950
2951 if (pkgSetting.origPackage != null) {
2952 // If we are first transitioning from an original package,
2953 // fix up the new package's name now. We need to do this after
2954 // looking up the package under its new name, so getPackageLP
2955 // can take care of fiddling things correctly.
2956 pkg.setPackageName(origPackage.name);
2957
2958 // File a report about this.
2959 String msg = "New package " + pkgSetting.realName
2960 + " renamed to replace old package " + pkgSetting.name;
2961 reportSettingsProblem(Log.WARN, msg);
2962
2963 // Make a note of it.
2964 mTransferedPackages.add(origPackage.name);
2965
2966 // No longer need to retain this.
2967 pkgSetting.origPackage = null;
2968 }
2969
2970 if (realName != null) {
2971 // Make a note of it.
2972 mTransferedPackages.add(pkg.packageName);
2973 }
2974
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002975 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2977 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 pkg.applicationInfo.uid = pkgSetting.userId;
2980 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002981
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002982 if (!verifySignaturesLP(pkgSetting, pkg)) {
Dianne Hackborn806da1d2010-03-18 16:50:07 -07002983 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 return null;
2985 }
2986 // The signature has changed, but this package is in the system
2987 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002988 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 // However... if this package is part of a shared user, but it
2990 // doesn't match the signature of the shared user, let's fail.
2991 // What this means is that you can't change the signatures
2992 // associated with an overall shared user, which doesn't seem all
2993 // that unreasonable.
2994 if (pkgSetting.sharedUser != null) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07002995 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
2996 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
2997 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2999 return null;
3000 }
3001 }
Dianne Hackborn806da1d2010-03-18 16:50:07 -07003002 // File a report about this.
3003 String msg = "System package " + pkg.packageName
3004 + " signature changed; retaining data.";
3005 reportSettingsProblem(Log.WARN, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003007
The Android Open Source Project10592532009-03-18 17:39:46 -07003008 // Verify that this new package doesn't have any content providers
3009 // that conflict with existing packages. Only do this if the
3010 // package isn't already installed, since we don't want to break
3011 // things that are installed.
3012 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
3013 int N = pkg.providers.size();
3014 int i;
3015 for (i=0; i<N; i++) {
3016 PackageParser.Provider p = pkg.providers.get(i);
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003017 if (p.info.authority != null) {
3018 String names[] = p.info.authority.split(";");
3019 for (int j = 0; j < names.length; j++) {
3020 if (mProviders.containsKey(names[j])) {
3021 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003022 Slog.w(TAG, "Can't install because provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003023 " (in package " + pkg.applicationInfo.packageName +
3024 ") is already used by "
3025 + ((other != null && other.getComponentName() != null)
3026 ? other.getComponentName().getPackageName() : "?"));
3027 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
3028 return null;
3029 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003030 }
3031 }
3032 }
3033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 }
3035
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003036 final String pkgName = pkg.packageName;
3037
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003038 if (pkg.mAdoptPermissions != null) {
3039 // This package wants to adopt ownership of permissions from
3040 // another package.
3041 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
3042 String origName = pkg.mAdoptPermissions.get(i);
3043 PackageSetting orig = mSettings.peekPackageLP(origName);
3044 if (orig != null) {
3045 if (verifyPackageUpdate(orig, pkg)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003046 Slog.i(TAG, "Adopting permissions from "
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003047 + origName + " to " + pkg.packageName);
3048 mSettings.transferPermissions(origName, pkg.packageName);
3049 }
3050 }
3051 }
3052 }
3053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 long scanFileTime = scanFile.lastModified();
3055 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
3056 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
3057 pkg.applicationInfo.processName = fixProcessName(
3058 pkg.applicationInfo.packageName,
3059 pkg.applicationInfo.processName,
3060 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061
3062 File dataPath;
3063 if (mPlatformPackage == pkg) {
3064 // The system package is special.
3065 dataPath = new File (Environment.getDataDirectory(), "system");
3066 pkg.applicationInfo.dataDir = dataPath.getPath();
3067 } else {
3068 // This is a normal package, need to make its data directory.
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08003069 dataPath = getDataPathForPackage(pkg);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003070
3071 boolean uidError = false;
3072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 if (dataPath.exists()) {
3074 mOutPermissions[1] = 0;
3075 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
3076 if (mOutPermissions[1] == pkg.applicationInfo.uid
3077 || !Process.supportsProcesses()) {
3078 pkg.applicationInfo.dataDir = dataPath.getPath();
3079 } else {
3080 boolean recovered = false;
3081 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
3082 // If this is a system app, we can at least delete its
3083 // current data so the application will still work.
3084 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07003085 int ret = mInstaller.remove(pkgName);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003086 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 // Old data gone!
3088 String msg = "System package " + pkg.packageName
3089 + " has changed from uid: "
3090 + mOutPermissions[1] + " to "
3091 + pkg.applicationInfo.uid + "; old data erased";
3092 reportSettingsProblem(Log.WARN, msg);
3093 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003095 // And now re-install the app.
Oscar Montemayor1f4df902010-03-26 18:44:14 -07003096 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 pkg.applicationInfo.uid);
3098 if (ret == -1) {
3099 // Ack should not happen!
3100 msg = "System package " + pkg.packageName
3101 + " could not have data directory re-created after delete.";
3102 reportSettingsProblem(Log.WARN, msg);
3103 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3104 return null;
3105 }
3106 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003108 if (!recovered) {
3109 mHasSystemUidErrors = true;
3110 }
3111 }
3112 if (!recovered) {
3113 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
3114 + pkg.applicationInfo.uid + "/fs_"
3115 + mOutPermissions[1];
3116 String msg = "Package " + pkg.packageName
3117 + " has mismatched uid: "
3118 + mOutPermissions[1] + " on disk, "
3119 + pkg.applicationInfo.uid + " in settings";
3120 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003121 mSettings.mReadMessages.append(msg);
3122 mSettings.mReadMessages.append('\n');
3123 uidError = true;
3124 if (!pkgSetting.uidError) {
3125 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128 }
3129 }
3130 pkg.applicationInfo.dataDir = dataPath.getPath();
3131 } else {
3132 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
3133 Log.v(TAG, "Want this data dir: " + dataPath);
3134 //invoke installer to do the actual installation
3135 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07003136 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 pkg.applicationInfo.uid);
3138 if(ret < 0) {
3139 // Error from installer
3140 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
3141 return null;
3142 }
3143 } else {
3144 dataPath.mkdirs();
3145 if (dataPath.exists()) {
3146 FileUtils.setPermissions(
3147 dataPath.toString(),
3148 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3149 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
3150 }
3151 }
3152 if (dataPath.exists()) {
3153 pkg.applicationInfo.dataDir = dataPath.getPath();
3154 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003155 Slog.w(TAG, "Unable to create data directory: " + dataPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 pkg.applicationInfo.dataDir = null;
3157 }
3158 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08003159
3160 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003161 }
3162
3163 // Perform shared library installation and dex validation and
3164 // optimization, if this is not a system app.
3165 if (mInstaller != null) {
3166 String path = scanFile.getPath();
3167 if (scanFileNewer) {
3168 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07003169 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
3170 if (err != PackageManager.INSTALL_SUCCEEDED) {
3171 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003172 return null;
3173 }
3174 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003175 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003176
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07003177 if ((scanMode&SCAN_NO_DEX) == 0) {
3178 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003179 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
3180 return null;
3181 }
3182 }
3183 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 if (mFactoryTest && pkg.requestedPermissions.contains(
3186 android.Manifest.permission.FACTORY_TEST)) {
3187 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
3188 }
3189
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003190 // Request the ActivityManager to kill the process(only for existing packages)
3191 // so that we do not end up in a confused state while the user is still using the older
3192 // version of the application while the new one gets installed.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003193 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003194 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003195 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003196 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 synchronized (mPackages) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08003199 // We don't expect installation to fail beyond this point,
3200 if ((scanMode&SCAN_MONITOR) != 0) {
3201 mAppDirs.put(pkg.mPath, pkg);
3202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003204 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07003206 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08003207 // Make sure we don't accidentally delete its data.
3208 mSettings.mPackagesToBeCleaned.remove(pkgName);
3209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003210 int N = pkg.providers.size();
3211 StringBuilder r = null;
3212 int i;
3213 for (i=0; i<N; i++) {
3214 PackageParser.Provider p = pkg.providers.get(i);
3215 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
3216 p.info.processName, pkg.applicationInfo.uid);
3217 mProvidersByComponent.put(new ComponentName(p.info.packageName,
3218 p.info.name), p);
3219 p.syncable = p.info.isSyncable;
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003220 if (p.info.authority != null) {
3221 String names[] = p.info.authority.split(";");
3222 p.info.authority = null;
3223 for (int j = 0; j < names.length; j++) {
3224 if (j == 1 && p.syncable) {
3225 // We only want the first authority for a provider to possibly be
3226 // syncable, so if we already added this provider using a different
3227 // authority clear the syncable flag. We copy the provider before
3228 // changing it because the mProviders object contains a reference
3229 // to a provider that we don't want to change.
3230 // Only do this for the second authority since the resulting provider
3231 // object can be the same for all future authorities for this provider.
3232 p = new PackageParser.Provider(p);
3233 p.syncable = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 }
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003235 if (!mProviders.containsKey(names[j])) {
3236 mProviders.put(names[j], p);
3237 if (p.info.authority == null) {
3238 p.info.authority = names[j];
3239 } else {
3240 p.info.authority = p.info.authority + ";" + names[j];
3241 }
3242 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
3243 Log.d(TAG, "Registered content provider: " + names[j] +
3244 ", className = " + p.info.name +
3245 ", isSyncable = " + p.info.isSyncable);
3246 } else {
3247 PackageParser.Provider other = mProviders.get(names[j]);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003248 Slog.w(TAG, "Skipping provider name " + names[j] +
Suchi Amalapurapu9444bea2010-03-05 10:46:11 -08003249 " (in package " + pkg.applicationInfo.packageName +
3250 "): name already used by "
3251 + ((other != null && other.getComponentName() != null)
3252 ? other.getComponentName().getPackageName() : "?"));
3253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 }
3255 }
3256 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3257 if (r == null) {
3258 r = new StringBuilder(256);
3259 } else {
3260 r.append(' ');
3261 }
3262 r.append(p.info.name);
3263 }
3264 }
3265 if (r != null) {
3266 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3267 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 N = pkg.services.size();
3270 r = null;
3271 for (i=0; i<N; i++) {
3272 PackageParser.Service s = pkg.services.get(i);
3273 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
3274 s.info.processName, pkg.applicationInfo.uid);
3275 mServices.addService(s);
3276 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3277 if (r == null) {
3278 r = new StringBuilder(256);
3279 } else {
3280 r.append(' ');
3281 }
3282 r.append(s.info.name);
3283 }
3284 }
3285 if (r != null) {
3286 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3287 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 N = pkg.receivers.size();
3290 r = null;
3291 for (i=0; i<N; i++) {
3292 PackageParser.Activity a = pkg.receivers.get(i);
3293 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3294 a.info.processName, pkg.applicationInfo.uid);
3295 mReceivers.addActivity(a, "receiver");
3296 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3297 if (r == null) {
3298 r = new StringBuilder(256);
3299 } else {
3300 r.append(' ');
3301 }
3302 r.append(a.info.name);
3303 }
3304 }
3305 if (r != null) {
3306 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3307 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 N = pkg.activities.size();
3310 r = null;
3311 for (i=0; i<N; i++) {
3312 PackageParser.Activity a = pkg.activities.get(i);
3313 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
3314 a.info.processName, pkg.applicationInfo.uid);
3315 mActivities.addActivity(a, "activity");
3316 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3317 if (r == null) {
3318 r = new StringBuilder(256);
3319 } else {
3320 r.append(' ');
3321 }
3322 r.append(a.info.name);
3323 }
3324 }
3325 if (r != null) {
3326 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3327 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 N = pkg.permissionGroups.size();
3330 r = null;
3331 for (i=0; i<N; i++) {
3332 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
3333 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
3334 if (cur == null) {
3335 mPermissionGroups.put(pg.info.name, pg);
3336 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3337 if (r == null) {
3338 r = new StringBuilder(256);
3339 } else {
3340 r.append(' ');
3341 }
3342 r.append(pg.info.name);
3343 }
3344 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003345 Slog.w(TAG, "Permission group " + pg.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 + pg.info.packageName + " ignored: original from "
3347 + cur.info.packageName);
3348 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3349 if (r == null) {
3350 r = new StringBuilder(256);
3351 } else {
3352 r.append(' ');
3353 }
3354 r.append("DUP:");
3355 r.append(pg.info.name);
3356 }
3357 }
3358 }
3359 if (r != null) {
3360 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
3361 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 N = pkg.permissions.size();
3364 r = null;
3365 for (i=0; i<N; i++) {
3366 PackageParser.Permission p = pkg.permissions.get(i);
3367 HashMap<String, BasePermission> permissionMap =
3368 p.tree ? mSettings.mPermissionTrees
3369 : mSettings.mPermissions;
3370 p.group = mPermissionGroups.get(p.info.group);
3371 if (p.info.group == null || p.group != null) {
3372 BasePermission bp = permissionMap.get(p.info.name);
3373 if (bp == null) {
3374 bp = new BasePermission(p.info.name, p.info.packageName,
3375 BasePermission.TYPE_NORMAL);
3376 permissionMap.put(p.info.name, bp);
3377 }
3378 if (bp.perm == null) {
3379 if (bp.sourcePackage == null
3380 || bp.sourcePackage.equals(p.info.packageName)) {
3381 BasePermission tree = findPermissionTreeLP(p.info.name);
3382 if (tree == null
3383 || tree.sourcePackage.equals(p.info.packageName)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003384 bp.packageSetting = pkgSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 bp.perm = p;
3386 bp.uid = pkg.applicationInfo.uid;
3387 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3388 if (r == null) {
3389 r = new StringBuilder(256);
3390 } else {
3391 r.append(' ');
3392 }
3393 r.append(p.info.name);
3394 }
3395 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003396 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 + p.info.packageName + " ignored: base tree "
3398 + tree.name + " is from package "
3399 + tree.sourcePackage);
3400 }
3401 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003402 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 + p.info.packageName + " ignored: original from "
3404 + bp.sourcePackage);
3405 }
3406 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3407 if (r == null) {
3408 r = new StringBuilder(256);
3409 } else {
3410 r.append(' ');
3411 }
3412 r.append("DUP:");
3413 r.append(p.info.name);
3414 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003415 if (bp.perm == p) {
3416 bp.protectionLevel = p.info.protectionLevel;
3417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003419 Slog.w(TAG, "Permission " + p.info.name + " from package "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 + p.info.packageName + " ignored: no group "
3421 + p.group);
3422 }
3423 }
3424 if (r != null) {
3425 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 N = pkg.instrumentation.size();
3429 r = null;
3430 for (i=0; i<N; i++) {
3431 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3432 a.info.packageName = pkg.applicationInfo.packageName;
3433 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3434 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3435 a.info.dataDir = pkg.applicationInfo.dataDir;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003436 mInstrumentation.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3438 if (r == null) {
3439 r = new StringBuilder(256);
3440 } else {
3441 r.append(' ');
3442 }
3443 r.append(a.info.name);
3444 }
3445 }
3446 if (r != null) {
3447 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3448 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003449
Dianne Hackborn854060af2009-07-09 18:14:31 -07003450 if (pkg.protectedBroadcasts != null) {
3451 N = pkg.protectedBroadcasts.size();
3452 for (i=0; i<N; i++) {
3453 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3454 }
3455 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 pkgSetting.setTimeStamp(scanFileTime);
3458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 return pkg;
3461 }
3462
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003463 private void killApplication(String pkgName, int uid) {
3464 // Request the ActivityManager to kill the process(only for existing packages)
3465 // so that we do not end up in a confused state while the user is still using the older
3466 // version of the application while the new one gets installed.
3467 IActivityManager am = ActivityManagerNative.getDefault();
3468 if (am != null) {
3469 try {
3470 am.killApplicationWithUid(pkgName, uid);
3471 } catch (RemoteException e) {
3472 }
3473 }
3474 }
3475
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003476 // The following constants are returned by cachePackageSharedLibsForAbiLI
3477 // to indicate if native shared libraries were found in the package.
3478 // Values are:
3479 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
3480 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
3481 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
3482 // in package (and not installed)
3483 //
3484 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
3485 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
3486 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003487
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003488 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
3489 // and automatically copy them to /data/data/<appname>/lib if present.
3490 //
3491 // NOTE: this method may throw an IOException if the library cannot
3492 // be copied to its final destination, e.g. if there isn't enough
3493 // room left on the data partition, or a ZipException if the package
3494 // file is malformed.
3495 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003496 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
3497 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003498 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
3499 final String apkLib = "lib/";
3500 final int apkLibLen = apkLib.length();
3501 final int cpuAbiLen = cpuAbi.length();
3502 final String libPrefix = "lib";
3503 final int libPrefixLen = libPrefix.length();
3504 final String libSuffix = ".so";
3505 final int libSuffixLen = libSuffix.length();
3506 boolean hasNativeLibraries = false;
3507 boolean installedNativeLibraries = false;
3508
3509 // the minimum length of a valid native shared library of the form
3510 // lib/<something>/lib<name>.so.
3511 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
3512
3513 ZipFile zipFile = new ZipFile(scanFile);
3514 Enumeration<ZipEntry> entries =
3515 (Enumeration<ZipEntry>) zipFile.entries();
3516
3517 while (entries.hasMoreElements()) {
3518 ZipEntry entry = entries.nextElement();
3519 // skip directories
3520 if (entry.isDirectory()) {
3521 continue;
3522 }
3523 String entryName = entry.getName();
3524
3525 // check that the entry looks like lib/<something>/lib<name>.so
3526 // here, but don't check the ABI just yet.
3527 //
3528 // - must be sufficiently long
3529 // - must end with libSuffix, i.e. ".so"
3530 // - must start with apkLib, i.e. "lib/"
3531 if (entryName.length() < minEntryLen ||
3532 !entryName.endsWith(libSuffix) ||
3533 !entryName.startsWith(apkLib) ) {
3534 continue;
3535 }
3536
3537 // file name must start with libPrefix, i.e. "lib"
3538 int lastSlash = entryName.lastIndexOf('/');
3539
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003540 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003541 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
3542 continue;
3543 }
3544
3545 hasNativeLibraries = true;
3546
3547 // check the cpuAbi now, between lib/ and /lib<name>.so
3548 //
3549 if (lastSlash != apkLibLen + cpuAbiLen ||
3550 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3551 continue;
3552
3553 // extract the library file name, ensure it doesn't contain
3554 // weird characters. we're guaranteed here that it doesn't contain
3555 // a directory separator though.
3556 String libFileName = entryName.substring(lastSlash+1);
3557 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3558 continue;
3559 }
3560
3561 installedNativeLibraries = true;
3562
3563 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3564 File.separator + libFileName;
3565 File sharedLibraryFile = new File(sharedLibraryFilePath);
3566 if (! sharedLibraryFile.exists() ||
3567 sharedLibraryFile.length() != entry.getSize() ||
3568 sharedLibraryFile.lastModified() != entry.getTime()) {
3569 if (Config.LOGD) {
3570 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003572 if (mInstaller == null) {
3573 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003574 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003575 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003576 sharedLibraryFile);
3577 }
3578 }
3579 if (!hasNativeLibraries)
3580 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3581
3582 if (!installedNativeLibraries)
3583 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3584
3585 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3586 }
3587
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003588 // Find the gdbserver executable program in a package at
3589 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3590 //
3591 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3592 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3593 //
3594 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3595 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3596 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3597 final String GDBSERVER = "gdbserver";
3598 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3599
3600 ZipFile zipFile = new ZipFile(scanFile);
3601 Enumeration<ZipEntry> entries =
3602 (Enumeration<ZipEntry>) zipFile.entries();
3603
3604 while (entries.hasMoreElements()) {
3605 ZipEntry entry = entries.nextElement();
3606 // skip directories
3607 if (entry.isDirectory()) {
3608 continue;
3609 }
3610 String entryName = entry.getName();
3611
3612 if (!entryName.equals(apkGdbServerPath)) {
3613 continue;
3614 }
3615
3616 String installGdbServerPath = installGdbServerDir.getPath() +
3617 "/" + GDBSERVER;
3618 File installGdbServerFile = new File(installGdbServerPath);
3619 if (! installGdbServerFile.exists() ||
3620 installGdbServerFile.length() != entry.getSize() ||
3621 installGdbServerFile.lastModified() != entry.getTime()) {
3622 if (Config.LOGD) {
3623 Log.d(TAG, "Caching gdbserver " + entry.getName());
3624 }
3625 if (mInstaller == null) {
3626 installGdbServerDir.mkdir();
3627 }
3628 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3629 installGdbServerFile);
3630 }
3631 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3632 }
3633 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3634 }
3635
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003636 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3637 // and copy them to /data/data/<appname>/lib.
3638 //
3639 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3640 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3641 // one if ro.product.cpu.abi2 is defined.
3642 //
3643 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3644 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003645 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003646 try {
3647 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3648
3649 // some architectures are capable of supporting several CPU ABIs
3650 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3651 // this is indicated by the definition of the ro.product.cpu.abi2
3652 // system property.
3653 //
3654 // only scan the package twice in case of ABI mismatch
3655 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003656 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003657 if (cpuAbi2 != null) {
3658 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003659 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003660
3661 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003662 Slog.w(TAG,"Native ABI mismatch from package file");
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003663 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003665
3666 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3667 cpuAbi = cpuAbi2;
3668 }
3669 }
3670
3671 // for debuggable packages, also extract gdbserver from lib/<abi>
3672 // into /data/data/<appname>/lib too.
3673 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3674 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3675 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3676 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3677 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003680 } catch (ZipException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003681 Slog.w(TAG, "Failed to extract data from package file", e);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003682 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003684 Slog.w(TAG, "Failed to cache package shared libs", e);
Dianne Hackbornb1811182009-05-21 15:45:42 -07003685 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003687 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 }
3689
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003690 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003692 File binaryDir,
3693 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 InputStream inputStream = zipFile.getInputStream(entry);
3695 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003696 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003698 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003699 // now need to be left as world readable and owned by the system.
3700 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3701 ! tempFile.setLastModified(entry.getTime()) ||
3702 FileUtils.setPermissions(tempFilePath,
3703 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003704 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003705 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003706 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003707 // Failed to properly write file.
3708 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003709 throw new IOException("Couldn't create cached binary "
3710 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 }
3712 } finally {
3713 inputStream.close();
3714 }
3715 }
3716
3717 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3718 if (chatty && Config.LOGD) Log.d(
3719 TAG, "Removing package " + pkg.applicationInfo.packageName );
3720
3721 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003722 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 mPackages.remove(pkg.applicationInfo.packageName);
3725 if (pkg.mPath != null) {
3726 mAppDirs.remove(pkg.mPath);
3727 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003729 PackageSetting ps = (PackageSetting)pkg.mExtras;
3730 if (ps != null && ps.sharedUser != null) {
3731 // XXX don't do this until the data is removed.
3732 if (false) {
3733 ps.sharedUser.packages.remove(ps);
3734 if (ps.sharedUser.packages.size() == 0) {
3735 // Remove.
3736 }
3737 }
3738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003740 int N = pkg.providers.size();
3741 StringBuilder r = null;
3742 int i;
3743 for (i=0; i<N; i++) {
3744 PackageParser.Provider p = pkg.providers.get(i);
3745 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3746 p.info.name));
3747 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 /* The is another ContentProvider with this authority when
3750 * this app was installed so this authority is null,
3751 * Ignore it as we don't have to unregister the provider.
3752 */
3753 continue;
3754 }
3755 String names[] = p.info.authority.split(";");
3756 for (int j = 0; j < names.length; j++) {
3757 if (mProviders.get(names[j]) == p) {
3758 mProviders.remove(names[j]);
3759 if (chatty && Config.LOGD) Log.d(
3760 TAG, "Unregistered content provider: " + names[j] +
3761 ", className = " + p.info.name +
3762 ", isSyncable = " + p.info.isSyncable);
3763 }
3764 }
3765 if (chatty) {
3766 if (r == null) {
3767 r = new StringBuilder(256);
3768 } else {
3769 r.append(' ');
3770 }
3771 r.append(p.info.name);
3772 }
3773 }
3774 if (r != null) {
3775 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003778 N = pkg.services.size();
3779 r = null;
3780 for (i=0; i<N; i++) {
3781 PackageParser.Service s = pkg.services.get(i);
3782 mServices.removeService(s);
3783 if (chatty) {
3784 if (r == null) {
3785 r = new StringBuilder(256);
3786 } else {
3787 r.append(' ');
3788 }
3789 r.append(s.info.name);
3790 }
3791 }
3792 if (r != null) {
3793 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3794 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 N = pkg.receivers.size();
3797 r = null;
3798 for (i=0; i<N; i++) {
3799 PackageParser.Activity a = pkg.receivers.get(i);
3800 mReceivers.removeActivity(a, "receiver");
3801 if (chatty) {
3802 if (r == null) {
3803 r = new StringBuilder(256);
3804 } else {
3805 r.append(' ');
3806 }
3807 r.append(a.info.name);
3808 }
3809 }
3810 if (r != null) {
3811 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3812 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003814 N = pkg.activities.size();
3815 r = null;
3816 for (i=0; i<N; i++) {
3817 PackageParser.Activity a = pkg.activities.get(i);
3818 mActivities.removeActivity(a, "activity");
3819 if (chatty) {
3820 if (r == null) {
3821 r = new StringBuilder(256);
3822 } else {
3823 r.append(' ');
3824 }
3825 r.append(a.info.name);
3826 }
3827 }
3828 if (r != null) {
3829 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3830 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003832 N = pkg.permissions.size();
3833 r = null;
3834 for (i=0; i<N; i++) {
3835 PackageParser.Permission p = pkg.permissions.get(i);
3836 boolean tree = false;
3837 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3838 if (bp == null) {
3839 tree = true;
3840 bp = mSettings.mPermissionTrees.get(p.info.name);
3841 }
3842 if (bp != null && bp.perm == p) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003843 bp.perm = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 if (chatty) {
3845 if (r == null) {
3846 r = new StringBuilder(256);
3847 } else {
3848 r.append(' ');
3849 }
3850 r.append(p.info.name);
3851 }
3852 }
3853 }
3854 if (r != null) {
3855 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3856 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 N = pkg.instrumentation.size();
3859 r = null;
3860 for (i=0; i<N; i++) {
3861 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08003862 mInstrumentation.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 if (chatty) {
3864 if (r == null) {
3865 r = new StringBuilder(256);
3866 } else {
3867 r.append(' ');
3868 }
3869 r.append(a.info.name);
3870 }
3871 }
3872 if (r != null) {
3873 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3874 }
3875 }
3876 }
3877
3878 private static final boolean isPackageFilename(String name) {
3879 return name != null && name.endsWith(".apk");
3880 }
3881
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003882 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
3883 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
3884 if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
3885 return true;
3886 }
3887 }
3888 return false;
3889 }
3890
3891 private void updatePermissionsLP(String changingPkg,
3892 PackageParser.Package pkgInfo, boolean grantPermissions, boolean replace) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 // Make sure there are no dangling permission trees.
3894 Iterator<BasePermission> it = mSettings.mPermissionTrees
3895 .values().iterator();
3896 while (it.hasNext()) {
3897 BasePermission bp = it.next();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003898 if (bp.packageSetting == null) {
3899 // We may not yet have parsed the package, so just see if
3900 // we still know about its settings.
3901 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3902 }
3903 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003904 Slog.w(TAG, "Removing dangling permission tree: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003905 + " from package " + bp.sourcePackage);
3906 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003907 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3908 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3909 Slog.i(TAG, "Removing old permission tree: " + bp.name
3910 + " from package " + bp.sourcePackage);
3911 grantPermissions = true;
3912 it.remove();
3913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 }
3915 }
3916
3917 // Make sure all dynamic permissions have been assigned to a package,
3918 // and make sure there are no dangling permissions.
3919 it = mSettings.mPermissions.values().iterator();
3920 while (it.hasNext()) {
3921 BasePermission bp = it.next();
3922 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3923 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3924 + bp.name + " pkg=" + bp.sourcePackage
3925 + " info=" + bp.pendingInfo);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003926 if (bp.packageSetting == null && bp.pendingInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003927 BasePermission tree = findPermissionTreeLP(bp.name);
3928 if (tree != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003929 bp.packageSetting = tree.packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930 bp.perm = new PackageParser.Permission(tree.perm.owner,
3931 new PermissionInfo(bp.pendingInfo));
3932 bp.perm.info.packageName = tree.perm.info.packageName;
3933 bp.perm.info.name = bp.name;
3934 bp.uid = tree.uid;
3935 }
3936 }
3937 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003938 if (bp.packageSetting == null) {
3939 // We may not yet have parsed the package, so just see if
3940 // we still know about its settings.
3941 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
3942 }
3943 if (bp.packageSetting == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08003944 Slog.w(TAG, "Removing dangling permission: " + bp.name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 + " from package " + bp.sourcePackage);
3946 it.remove();
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003947 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
3948 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
3949 Slog.i(TAG, "Removing old permission: " + bp.name
3950 + " from package " + bp.sourcePackage);
3951 grantPermissions = true;
3952 it.remove();
3953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954 }
3955 }
3956
3957 // Now update the permissions for all packages, in particular
3958 // replace the granted permissions of the system packages.
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003959 if (grantPermissions) {
3960 for (PackageParser.Package pkg : mPackages.values()) {
3961 if (pkg != pkgInfo) {
3962 grantPermissionsLP(pkg, false);
3963 }
3964 }
3965 }
3966
3967 if (pkgInfo != null) {
3968 grantPermissionsLP(pkgInfo, replace);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 }
3970 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3973 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3974 if (ps == null) {
3975 return;
3976 }
3977 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003978 boolean changedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003980 if (replace) {
3981 ps.permissionsFixed = false;
3982 if (gp == ps) {
3983 gp.grantedPermissions.clear();
3984 gp.gids = mGlobalGids;
3985 }
3986 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 if (gp.gids == null) {
3989 gp.gids = mGlobalGids;
3990 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 final int N = pkg.requestedPermissions.size();
3993 for (int i=0; i<N; i++) {
3994 String name = pkg.requestedPermissions.get(i);
3995 BasePermission bp = mSettings.mPermissions.get(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 if (false) {
3997 if (gp != ps) {
3998 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07003999 + ": " + bp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 }
4001 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004002 if (bp != null && bp.packageSetting != null) {
4003 final String perm = bp.name;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 boolean allowed;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004005 boolean allowedSig = false;
4006 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
4007 || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004008 allowed = true;
Dianne Hackborn6e52b5d2010-04-05 14:33:01 -07004009 } else if (bp.packageSetting == null) {
4010 // This permission is invalid; skip it.
4011 allowed = false;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004012 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
4013 || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
4014 allowed = (checkSignaturesLP(bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004016 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 == PackageManager.SIGNATURE_MATCH);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004018 if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
4020 // For updated system applications, the signatureOrSystem permission
4021 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004022 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
4024 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
4025 if(sysPs.grantedPermissions.contains(perm)) {
4026 allowed = true;
4027 } else {
4028 allowed = false;
4029 }
4030 } else {
4031 allowed = true;
4032 }
4033 }
4034 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004035 if (allowed) {
4036 allowedSig = true;
4037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 } else {
4039 allowed = false;
4040 }
4041 if (false) {
4042 if (gp != ps) {
4043 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
4044 }
4045 }
4046 if (allowed) {
4047 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
4048 && ps.permissionsFixed) {
4049 // If this is an existing, non-system package, then
4050 // we can't add any new permissions to it.
Dianne Hackbornf657b632010-03-22 18:08:07 -07004051 if (!allowedSig && !gp.grantedPermissions.contains(perm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07004053 // Except... if this is a permission that was added
4054 // to the platform (note: need to only do this when
4055 // updating the platform).
4056 final int NP = PackageParser.NEW_PERMISSIONS.length;
4057 for (int ip=0; ip<NP; ip++) {
4058 final PackageParser.NewPermissionInfo npi
4059 = PackageParser.NEW_PERMISSIONS[ip];
4060 if (npi.name.equals(perm)
4061 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
4062 allowed = true;
Dianne Hackbornf657b632010-03-22 18:08:07 -07004063 Log.i(TAG, "Auto-granting " + perm + " to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07004064 + pkg.packageName);
4065 break;
4066 }
4067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004068 }
4069 }
4070 if (allowed) {
4071 if (!gp.grantedPermissions.contains(perm)) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004072 changedPermission = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 gp.grantedPermissions.add(perm);
4074 gp.gids = appendInts(gp.gids, bp.gids);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004075 } else if (!ps.haveGids) {
4076 gp.gids = appendInts(gp.gids, bp.gids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 }
4078 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004079 Slog.w(TAG, "Not granting permission " + perm
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080 + " to package " + pkg.packageName
4081 + " because it was previously installed without");
4082 }
4083 } else {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004084 if (gp.grantedPermissions.remove(perm)) {
4085 changedPermission = true;
4086 gp.gids = removeInts(gp.gids, bp.gids);
4087 Slog.i(TAG, "Un-granting permission " + perm
4088 + " from package " + pkg.packageName
4089 + " (protectionLevel=" + bp.protectionLevel
4090 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4091 + ")");
4092 } else {
4093 Slog.w(TAG, "Not granting permission " + perm
4094 + " to package " + pkg.packageName
4095 + " (protectionLevel=" + bp.protectionLevel
4096 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
4097 + ")");
4098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 }
4100 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004101 Slog.w(TAG, "Unknown permission " + name
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 + " in package " + pkg.packageName);
4103 }
4104 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004105
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004106 if ((changedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004107 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
4108 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004109 // This is the first that we have heard about this package, so the
4110 // permissions we have now selected are fixed until explicitly
4111 // changed.
4112 ps.permissionsFixed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 }
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07004114 ps.haveGids = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004117 private final class ActivityIntentResolver
4118 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02004119 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004121 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 }
4123
Mihai Preda074edef2009-05-18 17:13:31 +02004124 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004126 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004127 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4128 }
4129
Mihai Predaeae850c2009-05-13 10:13:48 +02004130 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4131 ArrayList<PackageParser.Activity> packageActivities) {
4132 if (packageActivities == null) {
4133 return null;
4134 }
4135 mFlags = flags;
4136 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4137 int N = packageActivities.size();
4138 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
4139 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02004140
4141 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02004142 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02004143 intentFilters = packageActivities.get(i).intents;
4144 if (intentFilters != null && intentFilters.size() > 0) {
4145 listCut.add(intentFilters);
4146 }
Mihai Predaeae850c2009-05-13 10:13:48 +02004147 }
4148 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4149 }
4150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 public final void addActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004152 mActivities.put(a.getComponentName(), a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 if (SHOW_INFO || Config.LOGV) Log.v(
4154 TAG, " " + type + " " +
4155 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4156 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4157 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004158 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004159 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
4160 if (SHOW_INFO || Config.LOGV) {
4161 Log.v(TAG, " IntentFilter:");
4162 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4163 }
4164 if (!intent.debugCheck()) {
4165 Log.w(TAG, "==> For Activity " + a.info.name);
4166 }
4167 addFilter(intent);
4168 }
4169 }
4170
4171 public final void removeActivity(PackageParser.Activity a, String type) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004172 mActivities.remove(a.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 if (SHOW_INFO || Config.LOGV) Log.v(
4174 TAG, " " + type + " " +
4175 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
4176 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
4177 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02004178 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
4180 if (SHOW_INFO || Config.LOGV) {
4181 Log.v(TAG, " IntentFilter:");
4182 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4183 }
4184 removeFilter(intent);
4185 }
4186 }
4187
4188 @Override
4189 protected boolean allowFilterResult(
4190 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
4191 ActivityInfo filterAi = filter.activity.info;
4192 for (int i=dest.size()-1; i>=0; i--) {
4193 ActivityInfo destAi = dest.get(i).activityInfo;
4194 if (destAi.name == filterAi.name
4195 && destAi.packageName == filterAi.packageName) {
4196 return false;
4197 }
4198 }
4199 return true;
4200 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004203 protected String packageForFilter(PackageParser.ActivityIntentInfo info) {
4204 return info.activity.owner.packageName;
4205 }
4206
4207 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
4209 int match) {
4210 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
4211 return null;
4212 }
4213 final PackageParser.Activity activity = info.activity;
4214 if (mSafeMode && (activity.info.applicationInfo.flags
4215 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4216 return null;
4217 }
4218 final ResolveInfo res = new ResolveInfo();
4219 res.activityInfo = PackageParser.generateActivityInfo(activity,
4220 mFlags);
4221 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4222 res.filter = info;
4223 }
4224 res.priority = info.getPriority();
4225 res.preferredOrder = activity.owner.mPreferredOrder;
4226 //System.out.println("Result: " + res.activityInfo.className +
4227 // " = " + res.priority);
4228 res.match = match;
4229 res.isDefault = info.hasDefault;
4230 res.labelRes = info.labelRes;
4231 res.nonLocalizedLabel = info.nonLocalizedLabel;
4232 res.icon = info.icon;
4233 return res;
4234 }
4235
4236 @Override
4237 protected void sortResults(List<ResolveInfo> results) {
4238 Collections.sort(results, mResolvePrioritySorter);
4239 }
4240
4241 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004242 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004244 out.print(prefix); out.print(
4245 Integer.toHexString(System.identityHashCode(filter.activity)));
4246 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004247 out.print(filter.activity.getComponentShortName());
4248 out.print(" filter ");
4249 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004250 }
4251
4252// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4253// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4254// final List<ResolveInfo> retList = Lists.newArrayList();
4255// while (i.hasNext()) {
4256// final ResolveInfo resolveInfo = i.next();
4257// if (isEnabledLP(resolveInfo.activityInfo)) {
4258// retList.add(resolveInfo);
4259// }
4260// }
4261// return retList;
4262// }
4263
4264 // Keys are String (activity class name), values are Activity.
4265 private final HashMap<ComponentName, PackageParser.Activity> mActivities
4266 = new HashMap<ComponentName, PackageParser.Activity>();
4267 private int mFlags;
4268 }
4269
4270 private final class ServiceIntentResolver
4271 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02004272 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02004274 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 }
4276
Mihai Preda074edef2009-05-18 17:13:31 +02004277 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02004279 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
4281 }
4282
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07004283 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
4284 ArrayList<PackageParser.Service> packageServices) {
4285 if (packageServices == null) {
4286 return null;
4287 }
4288 mFlags = flags;
4289 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
4290 int N = packageServices.size();
4291 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
4292 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
4293
4294 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
4295 for (int i = 0; i < N; ++i) {
4296 intentFilters = packageServices.get(i).intents;
4297 if (intentFilters != null && intentFilters.size() > 0) {
4298 listCut.add(intentFilters);
4299 }
4300 }
4301 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
4302 }
4303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 public final void addService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004305 mServices.put(s.getComponentName(), s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 if (SHOW_INFO || Config.LOGV) Log.v(
4307 TAG, " " + (s.info.nonLocalizedLabel != null
4308 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4309 if (SHOW_INFO || Config.LOGV) Log.v(
4310 TAG, " Class=" + s.info.name);
4311 int NI = s.intents.size();
4312 int j;
4313 for (j=0; j<NI; j++) {
4314 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4315 if (SHOW_INFO || Config.LOGV) {
4316 Log.v(TAG, " IntentFilter:");
4317 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4318 }
4319 if (!intent.debugCheck()) {
4320 Log.w(TAG, "==> For Service " + s.info.name);
4321 }
4322 addFilter(intent);
4323 }
4324 }
4325
4326 public final void removeService(PackageParser.Service s) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08004327 mServices.remove(s.getComponentName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 if (SHOW_INFO || Config.LOGV) Log.v(
4329 TAG, " " + (s.info.nonLocalizedLabel != null
4330 ? s.info.nonLocalizedLabel : s.info.name) + ":");
4331 if (SHOW_INFO || Config.LOGV) Log.v(
4332 TAG, " Class=" + s.info.name);
4333 int NI = s.intents.size();
4334 int j;
4335 for (j=0; j<NI; j++) {
4336 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
4337 if (SHOW_INFO || Config.LOGV) {
4338 Log.v(TAG, " IntentFilter:");
4339 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
4340 }
4341 removeFilter(intent);
4342 }
4343 }
4344
4345 @Override
4346 protected boolean allowFilterResult(
4347 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
4348 ServiceInfo filterSi = filter.service.info;
4349 for (int i=dest.size()-1; i>=0; i--) {
4350 ServiceInfo destAi = dest.get(i).serviceInfo;
4351 if (destAi.name == filterSi.name
4352 && destAi.packageName == filterSi.packageName) {
4353 return false;
4354 }
4355 }
4356 return true;
4357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004360 protected String packageForFilter(PackageParser.ServiceIntentInfo info) {
4361 return info.service.owner.packageName;
4362 }
4363
4364 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004365 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
4366 int match) {
4367 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
4368 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
4369 return null;
4370 }
4371 final PackageParser.Service service = info.service;
4372 if (mSafeMode && (service.info.applicationInfo.flags
4373 &ApplicationInfo.FLAG_SYSTEM) == 0) {
4374 return null;
4375 }
4376 final ResolveInfo res = new ResolveInfo();
4377 res.serviceInfo = PackageParser.generateServiceInfo(service,
4378 mFlags);
4379 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
4380 res.filter = filter;
4381 }
4382 res.priority = info.getPriority();
4383 res.preferredOrder = service.owner.mPreferredOrder;
4384 //System.out.println("Result: " + res.activityInfo.className +
4385 // " = " + res.priority);
4386 res.match = match;
4387 res.isDefault = info.hasDefault;
4388 res.labelRes = info.labelRes;
4389 res.nonLocalizedLabel = info.nonLocalizedLabel;
4390 res.icon = info.icon;
4391 return res;
4392 }
4393
4394 @Override
4395 protected void sortResults(List<ResolveInfo> results) {
4396 Collections.sort(results, mResolvePrioritySorter);
4397 }
4398
4399 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004400 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004401 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07004402 out.print(prefix); out.print(
4403 Integer.toHexString(System.identityHashCode(filter.service)));
4404 out.print(' ');
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004405 out.print(filter.service.getComponentShortName());
4406 out.print(" filter ");
4407 out.println(Integer.toHexString(System.identityHashCode(filter)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 }
4409
4410// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
4411// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
4412// final List<ResolveInfo> retList = Lists.newArrayList();
4413// while (i.hasNext()) {
4414// final ResolveInfo resolveInfo = (ResolveInfo) i;
4415// if (isEnabledLP(resolveInfo.serviceInfo)) {
4416// retList.add(resolveInfo);
4417// }
4418// }
4419// return retList;
4420// }
4421
4422 // Keys are String (activity class name), values are Activity.
4423 private final HashMap<ComponentName, PackageParser.Service> mServices
4424 = new HashMap<ComponentName, PackageParser.Service>();
4425 private int mFlags;
4426 };
4427
4428 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
4429 new Comparator<ResolveInfo>() {
4430 public int compare(ResolveInfo r1, ResolveInfo r2) {
4431 int v1 = r1.priority;
4432 int v2 = r2.priority;
4433 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
4434 if (v1 != v2) {
4435 return (v1 > v2) ? -1 : 1;
4436 }
4437 v1 = r1.preferredOrder;
4438 v2 = r2.preferredOrder;
4439 if (v1 != v2) {
4440 return (v1 > v2) ? -1 : 1;
4441 }
4442 if (r1.isDefault != r2.isDefault) {
4443 return r1.isDefault ? -1 : 1;
4444 }
4445 v1 = r1.match;
4446 v2 = r2.match;
4447 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4448 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4449 }
4450 };
4451
4452 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4453 new Comparator<ProviderInfo>() {
4454 public int compare(ProviderInfo p1, ProviderInfo p2) {
4455 final int v1 = p1.initOrder;
4456 final int v2 = p2.initOrder;
4457 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4458 }
4459 };
4460
4461 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
4462 IActivityManager am = ActivityManagerNative.getDefault();
4463 if (am != null) {
4464 try {
4465 final Intent intent = new Intent(action,
4466 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4467 if (extras != null) {
4468 intent.putExtras(extras);
4469 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004470 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 am.broadcastIntent(
4472 null, intent,
4473 null, null, 0, null, null, null, false, false);
4474 } catch (RemoteException ex) {
4475 }
4476 }
4477 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004478
4479 public String nextPackageToClean(String lastPackage) {
4480 synchronized (mPackages) {
4481 if (!mMediaMounted) {
4482 // If the external storage is no longer mounted at this point,
4483 // the caller may not have been able to delete all of this
4484 // packages files and can not delete any more. Bail.
4485 return null;
4486 }
4487 if (lastPackage != null) {
4488 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4489 }
4490 return mSettings.mPackagesToBeCleaned.size() > 0
4491 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4492 }
4493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004495 void schedulePackageCleaning(String packageName) {
4496 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4497 }
4498
4499 void startCleaningPackages() {
4500 synchronized (mPackages) {
4501 if (!mMediaMounted) {
4502 return;
4503 }
4504 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4505 return;
4506 }
4507 }
4508 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4509 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4510 IActivityManager am = ActivityManagerNative.getDefault();
4511 if (am != null) {
4512 try {
4513 am.startService(null, intent, null);
4514 } catch (RemoteException e) {
4515 }
4516 }
4517 }
4518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 private final class AppDirObserver extends FileObserver {
4520 public AppDirObserver(String path, int mask, boolean isrom) {
4521 super(path, mask);
4522 mRootDir = path;
4523 mIsRom = isrom;
4524 }
4525
4526 public void onEvent(int event, String path) {
4527 String removedPackage = null;
4528 int removedUid = -1;
4529 String addedPackage = null;
4530 int addedUid = -1;
4531
4532 synchronized (mInstallLock) {
4533 String fullPathStr = null;
4534 File fullPath = null;
4535 if (path != null) {
4536 fullPath = new File(mRootDir, path);
4537 fullPathStr = fullPath.getPath();
4538 }
4539
4540 if (Config.LOGV) Log.v(
4541 TAG, "File " + fullPathStr + " changed: "
4542 + Integer.toHexString(event));
4543
4544 if (!isPackageFilename(path)) {
4545 if (Config.LOGV) Log.v(
4546 TAG, "Ignoring change of non-package file: " + fullPathStr);
4547 return;
4548 }
4549
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004550 // Ignore packages that are being installed or
4551 // have just been installed.
4552 if (ignoreCodePath(fullPathStr)) {
4553 return;
4554 }
4555 PackageParser.Package p = null;
4556 synchronized (mPackages) {
4557 p = mAppDirs.get(fullPathStr);
4558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 if ((event&REMOVE_EVENTS) != 0) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004560 if (p != null) {
4561 removePackageLI(p, true);
4562 removedPackage = p.applicationInfo.packageName;
4563 removedUid = p.applicationInfo.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004564 }
4565 }
4566
4567 if ((event&ADD_EVENTS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004569 p = scanPackageLI(fullPath,
Dianne Hackborn806da1d2010-03-18 16:50:07 -07004570 (mIsRom ? PackageParser.PARSE_IS_SYSTEM
4571 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 PackageParser.PARSE_CHATTY |
4573 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08004574 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 if (p != null) {
4576 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07004577 updatePermissionsLP(p.packageName, p,
4578 p.permissions.size() > 0, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580 addedPackage = p.applicationInfo.packageName;
4581 addedUid = p.applicationInfo.uid;
4582 }
4583 }
4584 }
4585
4586 synchronized (mPackages) {
4587 mSettings.writeLP();
4588 }
4589 }
4590
4591 if (removedPackage != null) {
4592 Bundle extras = new Bundle(1);
4593 extras.putInt(Intent.EXTRA_UID, removedUid);
4594 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4595 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4596 }
4597 if (addedPackage != null) {
4598 Bundle extras = new Bundle(1);
4599 extras.putInt(Intent.EXTRA_UID, addedUid);
4600 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
4601 }
4602 }
4603
4604 private final String mRootDir;
4605 private final boolean mIsRom;
4606 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 /* Called when a downloaded package installation has been confirmed by the user */
4609 public void installPackage(
4610 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004611 installPackage(packageURI, observer, flags, null);
4612 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004613
Jacek Surazski65e13172009-04-28 15:26:38 +02004614 /* Called when a downloaded package installation has been confirmed by the user */
4615 public void installPackage(
4616 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4617 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 mContext.enforceCallingOrSelfPermission(
4619 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004620
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004621 Message msg = mHandler.obtainMessage(INIT_COPY);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004622 msg.obj = new InstallParams(packageURI, observer, flags,
4623 installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004624 mHandler.sendMessage(msg);
4625 }
4626
Christopher Tate1bb69062010-02-19 17:02:12 -08004627 public void finishPackageInstall(int token) {
4628 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token);
4629 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4630 mHandler.sendMessage(msg);
4631 }
4632
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004633 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 // Queue up an async operation since the package installation may take a little while.
4635 mHandler.post(new Runnable() {
4636 public void run() {
4637 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004638 // Result object to be returned
4639 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004640 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004641 res.uid = -1;
4642 res.pkg = null;
4643 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004644 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004645 args.doPreInstall(res.returnCode);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004646 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004647 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004648 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004649 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004651
4652 // A restore should be performed at this point if (a) the install
4653 // succeeded, (b) the operation is not an update, and (c) the new
4654 // package has a backupAgent defined.
4655 final boolean update = res.removedInfo.removedPackage != null;
Christopher Tate59eac4b2010-02-19 19:25:45 -08004656 boolean doRestore = (!update
4657 && res.pkg != null
4658 && res.pkg.applicationInfo.backupAgentName != null);
Christopher Tate1bb69062010-02-19 17:02:12 -08004659
4660 // Set up the post-install work request bookkeeping. This will be used
4661 // and cleaned up by the post-install event handling regardless of whether
4662 // there's a restore pass performed. Token values are >= 1.
4663 int token;
4664 if (mNextInstallToken < 0) mNextInstallToken = 1;
4665 token = mNextInstallToken++;
4666
4667 PostInstallData data = new PostInstallData(args, res);
4668 mRunningInstalls.put(token, data);
4669 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
4670
4671 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
4672 // Pass responsibility to the Backup Manager. It will perform a
4673 // restore if appropriate, then pass responsibility back to the
4674 // Package Manager to run the post-install observer callbacks
4675 // and broadcasts.
4676 IBackupManager bm = IBackupManager.Stub.asInterface(
4677 ServiceManager.getService(Context.BACKUP_SERVICE));
4678 if (bm != null) {
4679 if (DEBUG_INSTALL) Log.v(TAG, "token " + token
4680 + " to BM for possible restore");
4681 try {
4682 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
4683 } catch (RemoteException e) {
4684 // can't happen; the backup manager is local
4685 } catch (Exception e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004686 Slog.e(TAG, "Exception trying to enqueue restore", e);
Christopher Tate1bb69062010-02-19 17:02:12 -08004687 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004688 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004689 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004690 Slog.e(TAG, "Backup Manager not found!");
Christopher Tate1bb69062010-02-19 17:02:12 -08004691 doRestore = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 }
Christopher Tate1bb69062010-02-19 17:02:12 -08004694
4695 if (!doRestore) {
4696 // No restore possible, or the Backup Manager was mysteriously not
4697 // available -- just fire the post-install work request directly.
4698 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
4699 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
4700 mHandler.sendMessage(msg);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 }
4703 });
4704 }
4705
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004706 abstract class HandlerParams {
4707 final static int MAX_RETRIES = 4;
4708 int retry = 0;
4709 final void startCopy() {
4710 try {
4711 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
4712 retry++;
4713 if (retry > MAX_RETRIES) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004714 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004715 mHandler.sendEmptyMessage(MCS_GIVE_UP);
4716 handleServiceError();
4717 return;
4718 } else {
4719 handleStartCopy();
4720 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND");
4721 mHandler.sendEmptyMessage(MCS_UNBIND);
4722 }
4723 } catch (RemoteException e) {
4724 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
4725 mHandler.sendEmptyMessage(MCS_RECONNECT);
4726 }
4727 handleReturnCode();
4728 }
4729
4730 final void serviceError() {
4731 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
4732 handleServiceError();
4733 handleReturnCode();
4734 }
4735 abstract void handleStartCopy() throws RemoteException;
4736 abstract void handleServiceError();
4737 abstract void handleReturnCode();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004738 }
4739
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004740 class InstallParams extends HandlerParams {
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004741 final IPackageInstallObserver observer;
4742 int flags;
4743 final Uri packageURI;
4744 final String installerPackageName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004745 private InstallArgs mArgs;
4746 private int mRet;
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004747 InstallParams(Uri packageURI,
4748 IPackageInstallObserver observer, int flags,
4749 String installerPackageName) {
4750 this.packageURI = packageURI;
4751 this.flags = flags;
4752 this.observer = observer;
4753 this.installerPackageName = installerPackageName;
4754 }
4755
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004756 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
4757 String packageName = pkgLite.packageName;
4758 int installLocation = pkgLite.installLocation;
4759 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
4760 synchronized (mPackages) {
4761 PackageParser.Package pkg = mPackages.get(packageName);
4762 if (pkg != null) {
4763 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
4764 // Check for updated system application.
4765 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4766 if (onSd) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004767 Slog.w(TAG, "Cannot install update to system app on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004768 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION;
4769 }
4770 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4771 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004772 if (onSd) {
4773 // Install flag overrides everything.
4774 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4775 }
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004776 // If current upgrade specifies particular preference
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004777 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
4778 // Application explicitly specified internal.
4779 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
4780 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
4781 // App explictly prefers external. Let policy decide
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004782 } else {
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004783 // Prefer previous location
Suchi Amalapurapu90d8ee62010-03-18 11:38:35 -07004784 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
4785 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4786 }
4787 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004788 }
4789 }
4790 } else {
4791 // Invalid install. Return error code
4792 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS;
4793 }
4794 }
4795 }
4796 // All the special cases have been taken care of.
4797 // Return result based on recommended install location.
4798 if (onSd) {
4799 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
4800 }
4801 return pkgLite.recommendedInstallLocation;
4802 }
4803
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004804 /*
4805 * Invoke remote method to get package information and install
4806 * location values. Override install location based on default
4807 * policy if needed and then create install arguments based
4808 * on the install location.
4809 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004810 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu1f9e1b42010-02-26 13:14:31 -08004811 int ret = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004812 boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
4813 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004814 boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
4815 if (onInt && onSd) {
4816 // Check if both bits are set.
4817 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
4818 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4819 } else if (fwdLocked && onSd) {
4820 // Check for forward locked apps
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08004821 Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004822 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004823 } else {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004824 // Remote call to find out default install location
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004825 PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004826 int loc = pkgLite.recommendedInstallLocation;
Suchi Amalapurapua2b6c372010-03-05 17:40:11 -08004827 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
4828 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
4829 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
4830 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4831 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004832 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4833 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
4834 ret = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004835 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
4836 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004837 } else {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004838 // Override with defaults if needed.
4839 loc = installLocationPolicy(pkgLite, flags);
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004840 if (!onSd && !onInt) {
4841 // Override install location with flags
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004842 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
4843 // Set the flag to install on external media.
4844 flags |= PackageManager.INSTALL_EXTERNAL;
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004845 flags &= ~PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004846 } else {
4847 // Make sure the flag for installing on external
4848 // media is unset
Suchi Amalapurapu14b6abd2010-03-17 08:37:04 -07004849 flags |= PackageManager.INSTALL_INTERNAL;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004850 flags &= ~PackageManager.INSTALL_EXTERNAL;
4851 }
4852 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004853 }
4854 }
4855 // Create the file args now.
4856 mArgs = createInstallArgs(this);
4857 if (ret == PackageManager.INSTALL_SUCCEEDED) {
4858 // Create copy only if we are not in an erroneous state.
4859 // Remote call to initiate copy using temporary file
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004860 ret = mArgs.copyApk(mContainerService, true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004861 }
4862 mRet = ret;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004863 }
4864
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004865 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004866 void handleReturnCode() {
4867 processPendingInstall(mArgs, mRet);
4868 }
4869
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004870 @Override
4871 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004872 mArgs = createInstallArgs(this);
4873 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004874 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004875 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004876
4877 /*
4878 * Utility class used in movePackage api.
4879 * srcArgs and targetArgs are not set for invalid flags and make
4880 * sure to do null checks when invoking methods on them.
4881 * We probably want to return ErrorPrams for both failed installs
4882 * and moves.
4883 */
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004884 class MoveParams extends HandlerParams {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004885 final IPackageMoveObserver observer;
4886 final int flags;
4887 final String packageName;
4888 final InstallArgs srcArgs;
4889 final InstallArgs targetArgs;
4890 int mRet;
4891 MoveParams(InstallArgs srcArgs,
4892 IPackageMoveObserver observer,
4893 int flags, String packageName) {
4894 this.srcArgs = srcArgs;
4895 this.observer = observer;
4896 this.flags = flags;
4897 this.packageName = packageName;
4898 if (srcArgs != null) {
4899 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
4900 targetArgs = createInstallArgs(packageUri, flags, packageName);
4901 } else {
4902 targetArgs = null;
4903 }
4904 }
4905
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004906 public void handleStartCopy() throws RemoteException {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004907 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4908 // Check for storage space on target medium
4909 if (!targetArgs.checkFreeStorage(mContainerService)) {
4910 Log.w(TAG, "Insufficient storage to install");
4911 return;
4912 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004913 // Create the file args now.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004914 mRet = targetArgs.copyApk(mContainerService, false);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004915 targetArgs.doPreInstall(mRet);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004916 if (DEBUG_SD_INSTALL) {
4917 StringBuilder builder = new StringBuilder();
4918 if (srcArgs != null) {
4919 builder.append("src: ");
4920 builder.append(srcArgs.getCodePath());
4921 }
4922 if (targetArgs != null) {
4923 builder.append(" target : ");
4924 builder.append(targetArgs.getCodePath());
4925 }
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004926 Log.i(TAG, builder.toString());
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004927 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004928 }
4929
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004930 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004931 void handleReturnCode() {
4932 targetArgs.doPostInstall(mRet);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004933 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
4934 if (mRet == PackageManager.INSTALL_SUCCEEDED) {
4935 currentStatus = PackageManager.MOVE_SUCCEEDED;
4936 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
4937 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
4938 }
4939 processPendingMove(this, currentStatus);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004940 }
4941
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004942 @Override
4943 void handleServiceError() {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004944 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004945 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004946 }
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08004947
4948 private InstallArgs createInstallArgs(InstallParams params) {
4949 if (installOnSd(params.flags)) {
4950 return new SdInstallArgs(params);
4951 } else {
4952 return new FileInstallArgs(params);
4953 }
4954 }
4955
4956 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
4957 if (installOnSd(flags)) {
4958 return new SdInstallArgs(fullCodePath, fullResourcePath);
4959 } else {
4960 return new FileInstallArgs(fullCodePath, fullResourcePath);
4961 }
4962 }
4963
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004964 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName) {
4965 if (installOnSd(flags)) {
4966 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
4967 return new SdInstallArgs(packageURI, cid);
4968 } else {
4969 return new FileInstallArgs(packageURI, pkgName);
4970 }
4971 }
4972
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004973 static abstract class InstallArgs {
4974 final IPackageInstallObserver observer;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08004975 // Always refers to PackageManager flags only
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004976 final int flags;
4977 final Uri packageURI;
4978 final String installerPackageName;
4979
4980 InstallArgs(Uri packageURI,
4981 IPackageInstallObserver observer, int flags,
4982 String installerPackageName) {
4983 this.packageURI = packageURI;
4984 this.flags = flags;
4985 this.observer = observer;
4986 this.installerPackageName = installerPackageName;
4987 }
4988
4989 abstract void createCopyFile();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08004990 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004991 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004992 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004993 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004994 abstract String getCodePath();
4995 abstract String getResourcePath();
4996 // Need installer lock especially for dex file removal.
4997 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004998 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08004999 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005000 }
5001
5002 class FileInstallArgs extends InstallArgs {
5003 File installDir;
5004 String codeFileName;
5005 String resourceFileName;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005006 boolean created = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005007
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005008 FileInstallArgs(InstallParams params) {
5009 super(params.packageURI, params.observer,
5010 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005011 }
5012
5013 FileInstallArgs(String fullCodePath, String fullResourcePath) {
5014 super(null, null, 0, null);
5015 File codeFile = new File(fullCodePath);
5016 installDir = codeFile.getParentFile();
5017 codeFileName = fullCodePath;
5018 resourceFileName = fullResourcePath;
5019 }
5020
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005021 FileInstallArgs(Uri packageURI, String pkgName) {
5022 super(packageURI, null, 0, null);
5023 boolean fwdLocked = isFwdLocked(flags);
5024 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
5025 String apkName = getNextCodePath(null, pkgName, ".apk");
5026 codeFileName = new File(installDir, apkName + ".apk").getPath();
5027 resourceFileName = getResourcePathFromCodePath();
5028 }
5029
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005030 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5031 return imcs.checkFreeStorage(false, packageURI);
5032 }
5033
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005034 String getCodePath() {
5035 return codeFileName;
5036 }
5037
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005038 void createCopyFile() {
5039 boolean fwdLocked = isFwdLocked(flags);
5040 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
5041 codeFileName = createTempPackageFile(installDir).getPath();
5042 resourceFileName = getResourcePathFromCodePath();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005043 created = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005044 }
5045
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005046 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005047 if (temp) {
5048 // Generate temp file name
5049 createCopyFile();
5050 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005051 // Get a ParcelFileDescriptor to write to the output file
5052 File codeFile = new File(codeFileName);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005053 if (!created) {
5054 try {
5055 codeFile.createNewFile();
5056 // Set permissions
5057 if (!setPermissions()) {
5058 // Failed setting permissions.
5059 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5060 }
5061 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005062 Slog.w(TAG, "Failed to create file " + codeFile);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005063 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5064 }
5065 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005066 ParcelFileDescriptor out = null;
5067 try {
5068 out = ParcelFileDescriptor.open(codeFile,
5069 ParcelFileDescriptor.MODE_READ_WRITE);
5070 } catch (FileNotFoundException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005071 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005072 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5073 }
5074 // Copy the resource now
5075 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5076 try {
5077 if (imcs.copyResource(packageURI, out)) {
5078 ret = PackageManager.INSTALL_SUCCEEDED;
5079 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005080 } finally {
5081 try { if (out != null) out.close(); } catch (IOException e) {}
5082 }
5083 return ret;
5084 }
5085
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005086 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005087 if (status != PackageManager.INSTALL_SUCCEEDED) {
5088 cleanUp();
5089 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005090 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005091 }
5092
5093 boolean doRename(int status, final String pkgName, String oldCodePath) {
5094 if (status != PackageManager.INSTALL_SUCCEEDED) {
5095 cleanUp();
5096 return false;
5097 } else {
5098 // Rename based on packageName
5099 File codeFile = new File(getCodePath());
5100 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
5101 File desFile = new File(installDir, apkName + ".apk");
5102 if (!codeFile.renameTo(desFile)) {
5103 return false;
5104 }
5105 // Reset paths since the file has been renamed.
5106 codeFileName = desFile.getPath();
5107 resourceFileName = getResourcePathFromCodePath();
5108 // Set permissions
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005109 if (!setPermissions()) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005110 // Failed setting permissions.
5111 return false;
5112 }
5113 return true;
5114 }
5115 }
5116
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005117 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005118 if (status != PackageManager.INSTALL_SUCCEEDED) {
5119 cleanUp();
5120 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005121 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005122 }
5123
5124 String getResourcePath() {
5125 return resourceFileName;
5126 }
5127
5128 String getResourcePathFromCodePath() {
5129 String codePath = getCodePath();
5130 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
5131 String apkNameOnly = getApkName(codePath);
5132 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
5133 } else {
5134 return codePath;
5135 }
5136 }
5137
5138 private boolean cleanUp() {
5139 boolean ret = true;
5140 String sourceDir = getCodePath();
5141 String publicSourceDir = getResourcePath();
5142 if (sourceDir != null) {
5143 File sourceFile = new File(sourceDir);
5144 if (!sourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005145 Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005146 ret = false;
5147 }
5148 // Delete application's code and resources
5149 sourceFile.delete();
5150 }
5151 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
5152 final File publicSourceFile = new File(publicSourceDir);
5153 if (!publicSourceFile.exists()) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005154 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005155 }
5156 if (publicSourceFile.exists()) {
5157 publicSourceFile.delete();
5158 }
5159 }
5160 return ret;
5161 }
5162
5163 void cleanUpResourcesLI() {
5164 String sourceDir = getCodePath();
5165 if (cleanUp() && mInstaller != null) {
5166 int retCode = mInstaller.rmdex(sourceDir);
5167 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005168 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005169 + " at location "
5170 + sourceDir + ", retcode=" + retCode);
5171 // we don't consider this to be a failure of the core package deletion
5172 }
5173 }
5174 }
5175
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005176 private boolean setPermissions() {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005177 // TODO Do this in a more elegant way later on. for now just a hack
5178 if (!isFwdLocked(flags)) {
5179 final int filePermissions =
5180 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
5181 |FileUtils.S_IROTH;
5182 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
5183 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005184 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005185 getCodePath()
5186 + ". The return code was: " + retCode);
5187 // TODO Define new internal error
5188 return false;
5189 }
5190 return true;
5191 }
5192 return true;
5193 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005194
5195 boolean doPostDeleteLI(boolean delete) {
5196 cleanUpResourcesLI();
5197 return true;
5198 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005199 }
5200
5201 class SdInstallArgs extends InstallArgs {
5202 String cid;
5203 String cachePath;
5204 static final String RES_FILE_NAME = "pkg.apk";
5205
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005206 SdInstallArgs(InstallParams params) {
5207 super(params.packageURI, params.observer,
5208 params.flags, params.installerPackageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005209 }
5210
5211 SdInstallArgs(String fullCodePath, String fullResourcePath) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005212 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005213 // Extract cid from fullCodePath
5214 int eidx = fullCodePath.lastIndexOf("/");
5215 String subStr1 = fullCodePath.substring(0, eidx);
5216 int sidx = subStr1.lastIndexOf("/");
5217 cid = subStr1.substring(sidx+1, eidx);
5218 cachePath = subStr1;
5219 }
5220
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005221 SdInstallArgs(String cid) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005222 super(null, null, PackageManager.INSTALL_EXTERNAL, null);
5223 this.cid = cid;
5224 }
5225
5226 SdInstallArgs(Uri packageURI, String cid) {
5227 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005228 this.cid = cid;
5229 }
5230
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005231 void createCopyFile() {
5232 cid = getTempContainerId();
5233 }
5234
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08005235 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
5236 return imcs.checkFreeStorage(true, packageURI);
5237 }
5238
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005239 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005240 if (temp) {
5241 createCopyFile();
5242 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005243 cachePath = imcs.copyResourceToContainer(
5244 packageURI, cid,
5245 getEncryptKey(), RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005246 return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
5247 PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005248 }
5249
5250 @Override
5251 String getCodePath() {
5252 return cachePath + "/" + RES_FILE_NAME;
5253 }
5254
5255 @Override
5256 String getResourcePath() {
5257 return cachePath + "/" + RES_FILE_NAME;
5258 }
5259
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005260 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005261 if (status != PackageManager.INSTALL_SUCCEEDED) {
5262 // Destroy container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005263 PackageHelper.destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005264 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005265 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005266 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005267 cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005268 if (cachePath == null) {
5269 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
5270 }
5271 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005272 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005273 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005274 }
5275
5276 boolean doRename(int status, final String pkgName,
5277 String oldCodePath) {
5278 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005279 String newCachePath = null;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005280 if (PackageHelper.isContainerMounted(cid)) {
5281 // Unmount the container
5282 if (!PackageHelper.unMountSdDir(cid)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005283 Slog.i(TAG, "Failed to unmount " + cid + " before renaming");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005284 return false;
5285 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005286 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005287 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
Suchi Amalapurapuc7537ee2010-03-24 09:27:19 -07005288 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId +
5289 " which might be stale. Will try to clean up.");
5290 // Clean up the stale container and proceed to recreate.
5291 if (!PackageHelper.destroySdDir(newCacheId)) {
5292 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId);
5293 return false;
5294 }
5295 // Successfully cleaned up stale container. Try to rename again.
5296 if (!PackageHelper.renameSdDir(cid, newCacheId)) {
5297 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId
5298 + " inspite of cleaning it up.");
5299 return false;
5300 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005301 }
5302 if (!PackageHelper.isContainerMounted(newCacheId)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005303 Slog.w(TAG, "Mounting container " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005304 newCachePath = PackageHelper.mountSdDir(newCacheId,
5305 getEncryptKey(), Process.SYSTEM_UID);
5306 } else {
5307 newCachePath = PackageHelper.getSdDir(newCacheId);
5308 }
5309 if (newCachePath == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005310 Slog.w(TAG, "Failed to get cache path for " + newCacheId);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08005311 return false;
5312 }
5313 Log.i(TAG, "Succesfully renamed " + cid +
5314 " at path: " + cachePath + " to " + newCacheId +
5315 " at new path: " + newCachePath);
5316 cid = newCacheId;
5317 cachePath = newCachePath;
5318 return true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005319 }
5320
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005321 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005322 if (status != PackageManager.INSTALL_SUCCEEDED) {
5323 cleanUp();
5324 } else {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005325 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005326 if (!mounted) {
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005327 PackageHelper.mountSdDir(cid,
5328 getEncryptKey(), Process.myUid());
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005329 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005330 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005331 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005332 }
5333
5334 private void cleanUp() {
5335 // Destroy secure container
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005336 PackageHelper.destroySdDir(cid);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005337 }
5338
5339 void cleanUpResourcesLI() {
5340 String sourceFile = getCodePath();
5341 // Remove dex file
5342 if (mInstaller != null) {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005343 int retCode = mInstaller.rmdex(sourceFile);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005344 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005345 Slog.w(TAG, "Couldn't remove dex file for package: "
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005346 + " at location "
5347 + sourceFile.toString() + ", retcode=" + retCode);
5348 // we don't consider this to be a failure of the core package deletion
5349 }
5350 }
5351 cleanUp();
5352 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005353
5354 boolean matchContainer(String app) {
5355 if (cid.startsWith(app)) {
5356 return true;
5357 }
5358 return false;
5359 }
5360
5361 String getPackageName() {
5362 int idx = cid.lastIndexOf("-");
5363 if (idx == -1) {
5364 return cid;
5365 }
5366 return cid.substring(0, idx);
5367 }
5368
5369 boolean doPostDeleteLI(boolean delete) {
5370 boolean ret = false;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005371 boolean mounted = PackageHelper.isContainerMounted(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005372 if (mounted) {
5373 // Unmount first
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08005374 ret = PackageHelper.unMountSdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005375 }
5376 if (ret && delete) {
5377 cleanUpResourcesLI();
5378 }
5379 return ret;
5380 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005381 };
5382
5383 // Utility method used to create code paths based on package name and available index.
5384 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
5385 String idxStr = "";
5386 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005387 // Fall back to default value of idx=1 if prefix is not
5388 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005389 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005390 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005391 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00005392 if (subStr.endsWith(suffix)) {
5393 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005394 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005395 // If oldCodePath already contains prefix find out the
5396 // ending index to either increment or decrement.
5397 int sidx = subStr.lastIndexOf(prefix);
5398 if (sidx != -1) {
5399 subStr = subStr.substring(sidx + prefix.length());
5400 if (subStr != null) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005401 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) {
5402 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005403 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005404 try {
5405 idx = Integer.parseInt(subStr);
5406 if (idx <= 1) {
5407 idx++;
5408 } else {
5409 idx--;
5410 }
5411 } catch(NumberFormatException e) {
5412 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005413 }
5414 }
5415 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005416 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005417 return prefix + idxStr;
5418 }
5419
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005420 // Utility method used to ignore ADD/REMOVE events
5421 // by directory observer.
5422 private static boolean ignoreCodePath(String fullPathStr) {
5423 String apkName = getApkName(fullPathStr);
5424 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
5425 if (idx != -1 && ((idx+1) < apkName.length())) {
5426 // Make sure the package ends with a numeral
5427 String version = apkName.substring(idx+1);
5428 try {
5429 Integer.parseInt(version);
5430 return true;
5431 } catch (NumberFormatException e) {}
5432 }
5433 return false;
5434 }
5435
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005436 // Utility method that returns the relative package path with respect
5437 // to the installation directory. Like say for /data/data/com.test-1.apk
5438 // string com.test-1 is returned.
5439 static String getApkName(String codePath) {
5440 if (codePath == null) {
5441 return null;
5442 }
5443 int sidx = codePath.lastIndexOf("/");
5444 int eidx = codePath.lastIndexOf(".");
5445 if (eidx == -1) {
5446 eidx = codePath.length();
5447 } else if (eidx == 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005448 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005449 return null;
5450 }
5451 return codePath.substring(sidx+1, eidx);
5452 }
5453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 class PackageInstalledInfo {
5455 String name;
5456 int uid;
5457 PackageParser.Package pkg;
5458 int returnCode;
5459 PackageRemovedInfo removedInfo;
5460 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 /*
5463 * Install a non-existing package.
5464 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005465 private void installNewPackageLI(PackageParser.Package pkg,
5466 int parseFlags,
5467 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005468 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005469 // Remember this for later, in case we need to rollback this install
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005470 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08005471
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08005472 boolean dataDirExists = getDataPathForPackage(pkg).exists();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 res.name = pkgName;
5474 synchronized(mPackages) {
Dianne Hackborne259bc72010-03-30 19:24:44 -07005475 if (mSettings.mRenamedPackages.containsKey(pkgName)) {
5476 // A package with the same name is already installed, though
5477 // it has been renamed to an older name. The package we
5478 // are trying to install should be installed as an update to
5479 // the existing one, but that has not been requested, so bail.
5480 Slog.w(TAG, "Attempt to re-install " + pkgName
5481 + " without first uninstalling package running as "
5482 + mSettings.mRenamedPackages.get(pkgName));
5483 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5484 return;
5485 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005486 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005487 // Don't allow installation over an existing package with the same name.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005488 Slog.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005489 + " without first uninstalling.");
5490 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
5491 return;
5492 }
5493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005495 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005497 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5499 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5500 }
5501 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005502 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005503 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 res);
5505 // delete the partially installed application. the data directory will have to be
5506 // restored if it was already existing
5507 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5508 // remove package from internal structures. Note that we want deletePackageX to
5509 // delete the package data and cache directories that it created in
5510 // scanPackageLocked, unless those directories existed before we even tried to
5511 // install.
5512 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005513 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
5515 res.removedInfo);
5516 }
5517 }
5518 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005519
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005520 private void replacePackageLI(PackageParser.Package pkg,
5521 int parseFlags,
5522 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005523 String installerPackageName, PackageInstalledInfo res) {
5524
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005525 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005526 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 // First find the old package info and check signatures
5528 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005529 oldPackage = mPackages.get(pkgName);
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005530 if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07005531 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
5533 return;
5534 }
5535 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005536 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005537 if (sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005538 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005540 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 }
5542 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005545 PackageParser.Package pkg,
5546 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005547 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 PackageParser.Package newPackage = null;
5549 String pkgName = deletedPackage.packageName;
5550 boolean deletedPkg = true;
5551 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005552
Jacek Surazski65e13172009-04-28 15:26:38 +02005553 String oldInstallerPackageName = null;
5554 synchronized (mPackages) {
5555 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
5556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005558 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005559 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 res.removedInfo)) {
5561 // If the existing package was'nt successfully deleted
5562 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5563 deletedPkg = false;
5564 } else {
5565 // Successfully deleted the old package. Now proceed with re-installation
5566 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005567 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005569 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5571 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08005572 }
5573 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005574 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005575 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 res);
5577 updatedSettings = true;
5578 }
5579 }
5580
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005581 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005582 // remove package from internal structures. Note that we want deletePackageX to
5583 // delete the package data and cache directories that it created in
5584 // scanPackageLocked, unless those directories existed before we even tried to
5585 // install.
5586 if(updatedSettings) {
5587 deletePackageLI(
5588 pkgName, true,
5589 PackageManager.DONT_DELETE_DATA,
5590 res.removedInfo);
5591 }
5592 // Since we failed to install the new package we need to restore the old
5593 // package that we deleted.
5594 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005595 File restoreFile = new File(deletedPackage.mPath);
5596 if (restoreFile == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005597 Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005598 return;
5599 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005600 // Parse old package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005601 boolean oldOnSd = isExternal(deletedPackage);
5602 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
5603 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5604 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
5605 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE;
5606 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode) == null) {
5607 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
5608 return;
5609 }
5610 // Restore of old package succeeded. Update permissions.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005611 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005612 updatePermissionsLP(deletedPackage.packageName, deletedPackage,
5613 true, false);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005614 mSettings.writeLP();
5615 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005616 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 }
5618 }
5619 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005622 PackageParser.Package pkg,
5623 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02005624 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 PackageParser.Package newPackage = null;
5626 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005627 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005628 PackageParser.PARSE_IS_SYSTEM;
5629 String packageName = deletedPackage.packageName;
5630 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
5631 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005632 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 return;
5634 }
5635 PackageParser.Package oldPkg;
5636 PackageSetting oldPkgSetting;
5637 synchronized (mPackages) {
5638 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005639 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
5641 (oldPkgSetting == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005642 Slog.w(TAG, "Couldn't find package:"+packageName+" information");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 return;
5644 }
5645 }
5646 res.removedInfo.uid = oldPkg.applicationInfo.uid;
5647 res.removedInfo.removedPackage = packageName;
5648 // Remove existing system package
5649 removePackageLI(oldPkg, true);
5650 synchronized (mPackages) {
5651 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
5652 }
5653
5654 // Successfully disabled the old package. Now proceed with re-installation
5655 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
5656 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005657 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005658 if (newPackage == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005659 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005660 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
5661 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
5662 }
5663 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005664 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005665 updatedSettings = true;
5666 }
5667
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005668 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005669 // Re installation failed. Restore old information
5670 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07005671 if (newPackage != null) {
5672 removePackageLI(newPackage, true);
5673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005675 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005676 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07005677 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005678 // Restore the old system information in Settings
5679 synchronized(mPackages) {
5680 if(updatedSettings) {
5681 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02005682 mSettings.setInstallerPackageName(packageName,
5683 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005684 }
5685 mSettings.writeLP();
5686 }
5687 }
5688 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005689
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005690 // Utility method used to move dex files during install.
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005691 private int moveDexFilesLI(PackageParser.Package newPackage) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005692 int retCode;
5693 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
5694 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
5695 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005696 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005697 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5698 }
5699 }
5700 return PackageManager.INSTALL_SUCCEEDED;
5701 }
5702
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005703 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02005704 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005705 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 synchronized (mPackages) {
5707 //write settings. the installStatus will be incomplete at this stage.
5708 //note that the new package setting would have already been
5709 //added to mPackages. It hasn't been persisted yet.
5710 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
5711 mSettings.writeLP();
5712 }
5713
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07005714 if ((res.returnCode = moveDexFilesLI(newPackage))
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005715 != PackageManager.INSTALL_SUCCEEDED) {
5716 // Discontinue if moving dex files failed.
5717 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08005719 if((res.returnCode = setPermissionsLI(newPackage))
5720 != PackageManager.INSTALL_SUCCEEDED) {
5721 if (mInstaller != null) {
5722 mInstaller.rmdex(newPackage.mScanPath);
5723 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005724 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005726 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005728 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07005729 updatePermissionsLP(newPackage.packageName, newPackage,
5730 newPackage.permissions.size() > 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 res.name = pkgName;
5732 res.uid = newPackage.applicationInfo.uid;
5733 res.pkg = newPackage;
5734 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005735 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005736 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5737 //to update install status
5738 mSettings.writeLP();
5739 }
5740 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005741
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005742 private void installPackageLI(InstallArgs args,
5743 boolean newInstall, PackageInstalledInfo res) {
5744 int pFlags = args.flags;
5745 String installerPackageName = args.installerPackageName;
5746 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005747 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08005748 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005749 boolean replace = false;
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005750 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005751 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005752 // Result object to be returned
5753 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5754
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005755 // Retrieve PackageSettings and parse package
5756 int parseFlags = PackageParser.PARSE_CHATTY |
5757 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5758 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5759 parseFlags |= mDefParseFlags;
5760 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5761 pp.setSeparateProcesses(mSeparateProcesses);
5762 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5763 null, mMetrics, parseFlags);
5764 if (pkg == null) {
5765 res.returnCode = pp.getParseError();
5766 return;
5767 }
5768 String pkgName = res.name = pkg.packageName;
5769 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5770 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5771 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5772 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005774 }
5775 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5776 res.returnCode = pp.getParseError();
5777 return;
5778 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005779 // Get rid of all references to package scan path via parser.
5780 pp = null;
5781 String oldCodePath = null;
5782 boolean systemApp = false;
5783 synchronized (mPackages) {
5784 // Check if installing already existing package
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005785 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
5786 String oldName = mSettings.mRenamedPackages.get(pkgName);
Dianne Hackbornc1552392010-03-03 16:19:01 -08005787 if (pkg.mOriginalPackages != null
5788 && pkg.mOriginalPackages.contains(oldName)
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005789 && mPackages.containsKey(oldName)) {
5790 // This package is derived from an original package,
5791 // and this device has been updating from that original
5792 // name. We must continue using the original name, so
5793 // rename the new package here.
Dianne Hackbornc1552392010-03-03 16:19:01 -08005794 pkg.setPackageName(oldName);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005795 pkgName = pkg.packageName;
5796 replace = true;
5797 } else if (mPackages.containsKey(pkgName)) {
5798 // This package, under its official name, already exists
5799 // on the device; we should replace it.
5800 replace = true;
5801 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005802 }
5803 PackageSetting ps = mSettings.mPackages.get(pkgName);
5804 if (ps != null) {
5805 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5806 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5807 systemApp = (ps.pkg.applicationInfo.flags &
5808 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005809 }
5810 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005811 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005812
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005813 if (systemApp && onSd) {
5814 // Disable updates to system apps on sdcard
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005815 Slog.w(TAG, "Cannot install updates to system apps on sdcard");
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005816 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5817 return;
5818 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08005819
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005820 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5821 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5822 return;
5823 }
5824 // Set application objects path explicitly after the rename
5825 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08005826 if (replace) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005827 replacePackageLI(pkg, parseFlags, scanMode,
5828 installerPackageName, res);
5829 } else {
5830 installNewPackageLI(pkg, parseFlags, scanMode,
5831 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 }
5833 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005834
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005835 private int setPermissionsLI(PackageParser.Package newPackage) {
5836 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005837 int retCode = 0;
5838 // TODO Gross hack but fix later. Ideally move this to be a post installation
5839 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005840 if ((newPackage.applicationInfo.flags
5841 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
5842 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 try {
5844 extractPublicFiles(newPackage, destResourceFile);
5845 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005846 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005847 " forward-locked app.");
5848 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5849 } finally {
5850 //TODO clean up the extracted public files
5851 }
5852 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005853 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 newPackage.applicationInfo.uid);
5855 } else {
5856 final int filePermissions =
5857 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005858 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 newPackage.applicationInfo.uid);
5860 }
5861 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005862 // The permissions on the resource file was set when it was copied for
5863 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 if (retCode != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005867 Slog.e(TAG, "Couldn't set new package file permissions for " +
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005868 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005870 // TODO Define new internal error
5871 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 }
5873 return PackageManager.INSTALL_SUCCEEDED;
5874 }
5875
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005876 private boolean isForwardLocked(PackageParser.Package pkg) {
5877 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 }
5879
Suchi Amalapurapuae181712010-03-30 14:01:02 -07005880 private boolean isExternal(PackageParser.Package pkg) {
5881 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
5882 }
5883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 private void extractPublicFiles(PackageParser.Package newPackage,
5885 File publicZipFile) throws IOException {
5886 final ZipOutputStream publicZipOutStream =
5887 new ZipOutputStream(new FileOutputStream(publicZipFile));
5888 final ZipFile privateZip = new ZipFile(newPackage.mPath);
5889
5890 // Copy manifest, resources.arsc and res directory to public zip
5891
5892 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
5893 while (privateZipEntries.hasMoreElements()) {
5894 final ZipEntry zipEntry = privateZipEntries.nextElement();
5895 final String zipEntryName = zipEntry.getName();
5896 if ("AndroidManifest.xml".equals(zipEntryName)
5897 || "resources.arsc".equals(zipEntryName)
5898 || zipEntryName.startsWith("res/")) {
5899 try {
5900 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
5901 } catch (IOException e) {
5902 try {
5903 publicZipOutStream.close();
5904 throw e;
5905 } finally {
5906 publicZipFile.delete();
5907 }
5908 }
5909 }
5910 }
5911
5912 publicZipOutStream.close();
5913 FileUtils.setPermissions(
5914 publicZipFile.getAbsolutePath(),
5915 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
5916 -1, -1);
5917 }
5918
5919 private static void copyZipEntry(ZipEntry zipEntry,
5920 ZipFile inZipFile,
5921 ZipOutputStream outZipStream) throws IOException {
5922 byte[] buffer = new byte[4096];
5923 int num;
5924
5925 ZipEntry newEntry;
5926 if (zipEntry.getMethod() == ZipEntry.STORED) {
5927 // Preserve the STORED method of the input entry.
5928 newEntry = new ZipEntry(zipEntry);
5929 } else {
5930 // Create a new entry so that the compressed len is recomputed.
5931 newEntry = new ZipEntry(zipEntry.getName());
5932 }
5933 outZipStream.putNextEntry(newEntry);
5934
5935 InputStream data = inZipFile.getInputStream(zipEntry);
5936 while ((num = data.read(buffer)) > 0) {
5937 outZipStream.write(buffer, 0, num);
5938 }
5939 outZipStream.flush();
5940 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 private void deleteTempPackageFiles() {
5943 FilenameFilter filter = new FilenameFilter() {
5944 public boolean accept(File dir, String name) {
5945 return name.startsWith("vmdl") && name.endsWith(".tmp");
5946 }
5947 };
5948 String tmpFilesList[] = mAppInstallDir.list(filter);
5949 if(tmpFilesList == null) {
5950 return;
5951 }
5952 for(int i = 0; i < tmpFilesList.length; i++) {
5953 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
5954 tmpFile.delete();
5955 }
5956 }
5957
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005958 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 File tmpPackageFile;
5960 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005961 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005963 Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 return null;
5965 }
5966 try {
5967 FileUtils.setPermissions(
5968 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
5969 -1, -1);
5970 } catch (IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08005971 Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005972 return null;
5973 }
5974 return tmpPackageFile;
5975 }
5976
5977 public void deletePackage(final String packageName,
5978 final IPackageDeleteObserver observer,
5979 final int flags) {
5980 mContext.enforceCallingOrSelfPermission(
5981 android.Manifest.permission.DELETE_PACKAGES, null);
5982 // Queue up an async operation since the package deletion may take a little while.
5983 mHandler.post(new Runnable() {
5984 public void run() {
5985 mHandler.removeCallbacks(this);
5986 final boolean succeded = deletePackageX(packageName, true, true, flags);
5987 if (observer != null) {
5988 try {
5989 observer.packageDeleted(succeded);
5990 } catch (RemoteException e) {
5991 Log.i(TAG, "Observer no longer exists.");
5992 } //end catch
5993 } //end if
5994 } //end run
5995 });
5996 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998 /**
5999 * This method is an internal method that could be get invoked either
6000 * to delete an installed package or to clean up a failed installation.
6001 * After deleting an installed package, a broadcast is sent to notify any
6002 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006003 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006004 * installation wouldn't have sent the initial broadcast either
6005 * The key steps in deleting a package are
6006 * deleting the package information in internal structures like mPackages,
6007 * deleting the packages base directories through installd
6008 * updating mSettings to reflect current status
6009 * persisting settings for later use
6010 * sending a broadcast if necessary
6011 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 private boolean deletePackageX(String packageName, boolean sendBroadCast,
6013 boolean deleteCodeAndResources, int flags) {
6014 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07006015 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006016
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006017 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
6018 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
6019 try {
6020 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006021 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08006022 return false;
6023 }
6024 } catch (RemoteException e) {
6025 }
6026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 synchronized (mInstallLock) {
6028 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
6029 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006031 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07006032 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
6033 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
6034
6035 // If the removed package was a system update, the old system packaged
6036 // was re-enabled; we need to broadcast this information
6037 if (systemUpdate) {
6038 Bundle extras = new Bundle(1);
6039 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
6040 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6041
6042 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
6043 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
6044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 }
Suchi Amalapurapud32c8022010-03-04 17:18:14 -08006046 // Force a gc here.
6047 Runtime.getRuntime().gc();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006048 // Delete the resources here after sending the broadcast to let
6049 // other processes clean up before deleting resources.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08006050 if (info.args != null) {
6051 synchronized (mInstallLock) {
6052 info.args.doPostDeleteLI(deleteCodeAndResources);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006053 }
6054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055 return res;
6056 }
6057
6058 static class PackageRemovedInfo {
6059 String removedPackage;
6060 int uid = -1;
6061 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07006062 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006063 // Clean up resources deleted packages.
6064 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07006065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006066 void sendBroadcast(boolean fullRemove, boolean replacing) {
6067 Bundle extras = new Bundle(1);
6068 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
6069 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
6070 if (replacing) {
6071 extras.putBoolean(Intent.EXTRA_REPLACING, true);
6072 }
6073 if (removedPackage != null) {
6074 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
6075 }
6076 if (removedUid >= 0) {
6077 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
6078 }
6079 }
6080 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006082 /*
6083 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
6084 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006085 * 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 -08006086 * delete a partially installed application.
6087 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006088 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006089 int flags) {
6090 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006091 if (outInfo != null) {
6092 outInfo.removedPackage = packageName;
6093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006094 removePackageLI(p, true);
6095 // Retrieve object to delete permissions for shared user later on
6096 PackageSetting deletedPs;
6097 synchronized (mPackages) {
6098 deletedPs = mSettings.mPackages.get(packageName);
6099 }
6100 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6101 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07006102 int retCode = mInstaller.remove(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006103 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006104 Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006105 + packageName + ", retcode=" + retCode);
6106 // we don't consider this to be a failure of the core package deletion
6107 }
6108 } else {
6109 //for emulator
6110 PackageParser.Package pkg = mPackages.get(packageName);
6111 File dataDir = new File(pkg.applicationInfo.dataDir);
6112 dataDir.delete();
6113 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006114 }
6115 synchronized (mPackages) {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006116 if (deletedPs != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006117 schedulePackageCleaning(packageName);
6118
6119 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
6120 if (outInfo != null) {
6121 outInfo.removedUid = mSettings.removePackageLP(packageName);
6122 }
6123 if (deletedPs != null) {
6124 updatePermissionsLP(deletedPs.name, null, false, false);
6125 if (deletedPs.sharedUser != null) {
6126 // remove permissions associated with package
6127 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
6128 }
6129 }
6130 }
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08006131 // remove from preferred activities.
6132 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
6133 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
6134 if (pa.mActivity.getPackageName().equals(deletedPs.name)) {
6135 removed.add(pa);
6136 }
6137 }
6138 for (PreferredActivity pa : removed) {
6139 mSettings.mPreferredActivities.removeFilter(pa);
6140 }
6141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006142 // Save settings now
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006143 mSettings.writeLP();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 }
6145 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006147 /*
6148 * Tries to delete system package.
6149 */
6150 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006151 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006152 ApplicationInfo applicationInfo = p.applicationInfo;
6153 //applicable for non-partially installed applications only
6154 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006155 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 return false;
6157 }
6158 PackageSetting ps = null;
6159 // Confirm if the system package has been updated
6160 // An updated system app can be deleted. This will also have to restore
6161 // the system pkg from system partition
6162 synchronized (mPackages) {
6163 ps = mSettings.getDisabledSystemPkg(p.packageName);
6164 }
6165 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006166 Slog.w(TAG, "Attempt to delete system package "+ p.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 return false;
6168 } else {
6169 Log.i(TAG, "Deleting system pkg from data partition");
6170 }
6171 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07006172 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006173 boolean deleteCodeAndResources = false;
6174 if (ps.versionCode < p.mVersionCode) {
6175 // Delete code and resources for downgrades
6176 deleteCodeAndResources = true;
6177 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
6178 flags &= ~PackageManager.DONT_DELETE_DATA;
6179 }
6180 } else {
6181 // Preserve data by setting flag
6182 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
6183 flags |= PackageManager.DONT_DELETE_DATA;
6184 }
6185 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
6187 if (!ret) {
6188 return false;
6189 }
6190 synchronized (mPackages) {
6191 // Reinstate the old system package
6192 mSettings.enableSystemPackageLP(p.packageName);
6193 }
6194 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006195 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006196 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006197 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 if (newPkg == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006200 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 return false;
6202 }
6203 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006204 updatePermissionsLP(newPkg.packageName, newPkg, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006205 mSettings.writeLP();
6206 }
6207 return true;
6208 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006210 private boolean deleteInstalledPackageLI(PackageParser.Package p,
6211 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
6212 ApplicationInfo applicationInfo = p.applicationInfo;
6213 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006214 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 return false;
6216 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006217 if (outInfo != null) {
6218 outInfo.uid = applicationInfo.uid;
6219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220
6221 // Delete package data from internal structures and also remove data if flag is set
6222 removePackageDataLI(p, outInfo, flags);
6223
6224 // Delete application code and resources
6225 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006226 // TODO can pick up from PackageSettings as well
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08006227 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ?
Suchi Amalapurapu5b993ce2010-02-12 09:43:29 -08006228 PackageManager.INSTALL_EXTERNAL : 0;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006229 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
6230 PackageManager.INSTALL_FORWARD_LOCK : 0;
6231 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006232 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006233 }
6234 return true;
6235 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 /*
6238 * This method handles package deletion in general
6239 */
6240 private boolean deletePackageLI(String packageName,
6241 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
6242 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006243 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006244 return false;
6245 }
6246 PackageParser.Package p;
6247 boolean dataOnly = false;
6248 synchronized (mPackages) {
6249 p = mPackages.get(packageName);
6250 if (p == null) {
6251 //this retrieves partially installed apps
6252 dataOnly = true;
6253 PackageSetting ps = mSettings.mPackages.get(packageName);
6254 if (ps == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006255 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 return false;
6257 }
6258 p = ps.pkg;
6259 }
6260 }
6261 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006262 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 return false;
6264 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 if (dataOnly) {
6267 // Delete application data first
6268 removePackageDataLI(p, outInfo, flags);
6269 return true;
6270 }
6271 // At this point the package should have ApplicationInfo associated with it
6272 if (p.applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006273 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006274 return false;
6275 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006276 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
6278 Log.i(TAG, "Removing system package:"+p.packageName);
6279 // When an updated system application is deleted we delete the existing resources as well and
6280 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006281 ret = deleteSystemPackageLI(p, flags, outInfo);
6282 } else {
6283 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08006284 // Kill application pre-emptively especially for apps on sd.
6285 killApplication(packageName, p.applicationInfo.uid);
Jeff Brown07330792010-03-30 19:57:08 -07006286 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006288 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006289 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 public void clearApplicationUserData(final String packageName,
6292 final IPackageDataObserver observer) {
6293 mContext.enforceCallingOrSelfPermission(
6294 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
6295 // Queue up an async operation since the package deletion may take a little while.
6296 mHandler.post(new Runnable() {
6297 public void run() {
6298 mHandler.removeCallbacks(this);
6299 final boolean succeeded;
6300 synchronized (mInstallLock) {
6301 succeeded = clearApplicationUserDataLI(packageName);
6302 }
6303 if (succeeded) {
6304 // invoke DeviceStorageMonitor's update method to clear any notifications
6305 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
6306 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
6307 if (dsm != null) {
6308 dsm.updateMemory();
6309 }
6310 }
6311 if(observer != null) {
6312 try {
6313 observer.onRemoveCompleted(packageName, succeeded);
6314 } catch (RemoteException e) {
6315 Log.i(TAG, "Observer no longer exists.");
6316 }
6317 } //end if observer
6318 } //end run
6319 });
6320 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 private boolean clearApplicationUserDataLI(String packageName) {
6323 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006324 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 return false;
6326 }
6327 PackageParser.Package p;
6328 boolean dataOnly = false;
6329 synchronized (mPackages) {
6330 p = mPackages.get(packageName);
6331 if(p == null) {
6332 dataOnly = true;
6333 PackageSetting ps = mSettings.mPackages.get(packageName);
6334 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006335 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 return false;
6337 }
6338 p = ps.pkg;
6339 }
6340 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08006341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 if(!dataOnly) {
6343 //need to check this only for fully installed applications
6344 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006345 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006346 return false;
6347 }
6348 final ApplicationInfo applicationInfo = p.applicationInfo;
6349 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006350 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 return false;
6352 }
6353 }
6354 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07006355 int retCode = mInstaller.clearUserData(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006357 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 + packageName);
6359 return false;
6360 }
6361 }
6362 return true;
6363 }
6364
6365 public void deleteApplicationCacheFiles(final String packageName,
6366 final IPackageDataObserver observer) {
6367 mContext.enforceCallingOrSelfPermission(
6368 android.Manifest.permission.DELETE_CACHE_FILES, null);
6369 // Queue up an async operation since the package deletion may take a little while.
6370 mHandler.post(new Runnable() {
6371 public void run() {
6372 mHandler.removeCallbacks(this);
6373 final boolean succeded;
6374 synchronized (mInstallLock) {
6375 succeded = deleteApplicationCacheFilesLI(packageName);
6376 }
6377 if(observer != null) {
6378 try {
6379 observer.onRemoveCompleted(packageName, succeded);
6380 } catch (RemoteException e) {
6381 Log.i(TAG, "Observer no longer exists.");
6382 }
6383 } //end if observer
6384 } //end run
6385 });
6386 }
6387
6388 private boolean deleteApplicationCacheFilesLI(String packageName) {
6389 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006390 Slog.w(TAG, "Attempt to delete null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 return false;
6392 }
6393 PackageParser.Package p;
6394 synchronized (mPackages) {
6395 p = mPackages.get(packageName);
6396 }
6397 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006398 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006399 return false;
6400 }
6401 final ApplicationInfo applicationInfo = p.applicationInfo;
6402 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006403 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006404 return false;
6405 }
6406 if (mInstaller != null) {
Oscar Montemayor1f4df902010-03-26 18:44:14 -07006407 int retCode = mInstaller.deleteCacheFiles(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006408 if (retCode < 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006409 Slog.w(TAG, "Couldn't remove cache files for package: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 + packageName);
6411 return false;
6412 }
6413 }
6414 return true;
6415 }
6416
6417 public void getPackageSizeInfo(final String packageName,
6418 final IPackageStatsObserver observer) {
6419 mContext.enforceCallingOrSelfPermission(
6420 android.Manifest.permission.GET_PACKAGE_SIZE, null);
6421 // Queue up an async operation since the package deletion may take a little while.
6422 mHandler.post(new Runnable() {
6423 public void run() {
6424 mHandler.removeCallbacks(this);
6425 PackageStats lStats = new PackageStats(packageName);
6426 final boolean succeded;
6427 synchronized (mInstallLock) {
6428 succeded = getPackageSizeInfoLI(packageName, lStats);
6429 }
6430 if(observer != null) {
6431 try {
6432 observer.onGetStatsCompleted(lStats, succeded);
6433 } catch (RemoteException e) {
6434 Log.i(TAG, "Observer no longer exists.");
6435 }
6436 } //end if observer
6437 } //end run
6438 });
6439 }
6440
6441 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
6442 if (packageName == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006443 Slog.w(TAG, "Attempt to get size of null packageName.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 return false;
6445 }
6446 PackageParser.Package p;
6447 boolean dataOnly = false;
6448 synchronized (mPackages) {
6449 p = mPackages.get(packageName);
6450 if(p == null) {
6451 dataOnly = true;
6452 PackageSetting ps = mSettings.mPackages.get(packageName);
6453 if((ps == null) || (ps.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006454 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 return false;
6456 }
6457 p = ps.pkg;
6458 }
6459 }
6460 String publicSrcDir = null;
6461 if(!dataOnly) {
6462 final ApplicationInfo applicationInfo = p.applicationInfo;
6463 if (applicationInfo == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006464 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006465 return false;
6466 }
6467 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
6468 }
6469 if (mInstaller != null) {
6470 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayor1f4df902010-03-26 18:44:14 -07006471 publicSrcDir, pStats);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006472 if (res < 0) {
6473 return false;
6474 } else {
6475 return true;
6476 }
6477 }
6478 return true;
6479 }
6480
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 public void addPackageToPreferred(String packageName) {
6483 mContext.enforceCallingOrSelfPermission(
6484 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006485 Slog.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 }
6487
6488 public void removePackageFromPreferred(String packageName) {
6489 mContext.enforceCallingOrSelfPermission(
6490 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006491 Slog.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 }
6493
6494 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006495 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 }
6497
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006498 int getUidTargetSdkVersionLockedLP(int uid) {
6499 Object obj = mSettings.getUserIdLP(uid);
6500 if (obj instanceof SharedUserSetting) {
6501 SharedUserSetting sus = (SharedUserSetting)obj;
6502 final int N = sus.packages.size();
6503 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
6504 Iterator<PackageSetting> it = sus.packages.iterator();
6505 int i=0;
6506 while (it.hasNext()) {
6507 PackageSetting ps = it.next();
6508 if (ps.pkg != null) {
6509 int v = ps.pkg.applicationInfo.targetSdkVersion;
6510 if (v < vers) vers = v;
6511 }
6512 }
6513 return vers;
6514 } else if (obj instanceof PackageSetting) {
6515 PackageSetting ps = (PackageSetting)obj;
6516 if (ps.pkg != null) {
6517 return ps.pkg.applicationInfo.targetSdkVersion;
6518 }
6519 }
6520 return Build.VERSION_CODES.CUR_DEVELOPMENT;
6521 }
6522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 public void addPreferredActivity(IntentFilter filter, int match,
6524 ComponentName[] set, ComponentName activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006526 if (mContext.checkCallingOrSelfPermission(
6527 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6528 != PackageManager.PERMISSION_GRANTED) {
6529 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6530 < Build.VERSION_CODES.FROYO) {
6531 Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
6532 + Binder.getCallingUid());
6533 return;
6534 }
6535 mContext.enforceCallingOrSelfPermission(
6536 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6537 }
6538
6539 Slog.i(TAG, "Adding preferred activity " + activity + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006540 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6541 mSettings.mPreferredActivities.addFilter(
6542 new PreferredActivity(filter, match, set, activity));
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006543 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 }
6545 }
6546
Satish Sampath8dbe6122009-06-02 23:35:54 +01006547 public void replacePreferredActivity(IntentFilter filter, int match,
6548 ComponentName[] set, ComponentName activity) {
Satish Sampath8dbe6122009-06-02 23:35:54 +01006549 if (filter.countActions() != 1) {
6550 throw new IllegalArgumentException(
6551 "replacePreferredActivity expects filter to have only 1 action.");
6552 }
6553 if (filter.countCategories() != 1) {
6554 throw new IllegalArgumentException(
6555 "replacePreferredActivity expects filter to have only 1 category.");
6556 }
6557 if (filter.countDataAuthorities() != 0
6558 || filter.countDataPaths() != 0
6559 || filter.countDataSchemes() != 0
6560 || filter.countDataTypes() != 0) {
6561 throw new IllegalArgumentException(
6562 "replacePreferredActivity expects filter to have no data authorities, " +
6563 "paths, schemes or types.");
6564 }
6565 synchronized (mPackages) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006566 if (mContext.checkCallingOrSelfPermission(
6567 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6568 != PackageManager.PERMISSION_GRANTED) {
6569 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6570 < Build.VERSION_CODES.FROYO) {
6571 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid "
6572 + Binder.getCallingUid());
6573 return;
6574 }
6575 mContext.enforceCallingOrSelfPermission(
6576 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6577 }
6578
Satish Sampath8dbe6122009-06-02 23:35:54 +01006579 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6580 String action = filter.getAction(0);
6581 String category = filter.getCategory(0);
6582 while (it.hasNext()) {
6583 PreferredActivity pa = it.next();
6584 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
6585 it.remove();
6586 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
6587 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
6588 }
6589 }
6590 addPreferredActivity(filter, match, set, activity);
6591 }
6592 }
6593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 public void clearPackagePreferredActivities(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006595 synchronized (mPackages) {
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006596 int uid = Binder.getCallingUid();
6597 PackageParser.Package pkg = mPackages.get(packageName);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006598 if (pkg == null || pkg.applicationInfo.uid != uid) {
6599 if (mContext.checkCallingOrSelfPermission(
6600 android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
6601 != PackageManager.PERMISSION_GRANTED) {
6602 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid())
6603 < Build.VERSION_CODES.FROYO) {
6604 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
6605 + Binder.getCallingUid());
6606 return;
6607 }
6608 mContext.enforceCallingOrSelfPermission(
6609 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
6610 }
Dianne Hackborn2ee89ea2010-03-10 18:27:09 -08006611 }
6612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 if (clearPackagePreferredActivitiesLP(packageName)) {
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006614 scheduleWriteSettingsLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 }
6616 }
6617 }
6618
6619 boolean clearPackagePreferredActivitiesLP(String packageName) {
6620 boolean changed = false;
6621 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6622 while (it.hasNext()) {
6623 PreferredActivity pa = it.next();
6624 if (pa.mActivity.getPackageName().equals(packageName)) {
6625 it.remove();
6626 changed = true;
6627 }
6628 }
6629 return changed;
6630 }
6631
6632 public int getPreferredActivities(List<IntentFilter> outFilters,
6633 List<ComponentName> outActivities, String packageName) {
6634
6635 int num = 0;
6636 synchronized (mPackages) {
6637 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
6638 while (it.hasNext()) {
6639 PreferredActivity pa = it.next();
6640 if (packageName == null
6641 || pa.mActivity.getPackageName().equals(packageName)) {
6642 if (outFilters != null) {
6643 outFilters.add(new IntentFilter(pa));
6644 }
6645 if (outActivities != null) {
6646 outActivities.add(pa.mActivity);
6647 }
6648 }
6649 }
6650 }
6651
6652 return num;
6653 }
6654
6655 public void setApplicationEnabledSetting(String appPackageName,
6656 int newState, int flags) {
6657 setEnabledSetting(appPackageName, null, newState, flags);
6658 }
6659
6660 public void setComponentEnabledSetting(ComponentName componentName,
6661 int newState, int flags) {
6662 setEnabledSetting(componentName.getPackageName(),
6663 componentName.getClassName(), newState, flags);
6664 }
6665
6666 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006667 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006668 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
6669 || newState == COMPONENT_ENABLED_STATE_ENABLED
6670 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
6671 throw new IllegalArgumentException("Invalid new component state: "
6672 + newState);
6673 }
6674 PackageSetting pkgSetting;
6675 final int uid = Binder.getCallingUid();
6676 final int permission = mContext.checkCallingPermission(
6677 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
6678 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006679 boolean sendNow = false;
6680 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006681 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006683 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006685 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006687 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006689 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006690 }
6691 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006692 "Unknown component: " + packageName
6693 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 }
6695 if (!allowedByPermission && (uid != pkgSetting.userId)) {
6696 throw new SecurityException(
6697 "Permission Denial: attempt to change component state from pid="
6698 + Binder.getCallingPid()
6699 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
6700 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006701 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 // We're dealing with an application/package level state change
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006703 if (pkgSetting.enabled == newState) {
6704 // Nothing to do
6705 return;
6706 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006707 pkgSetting.enabled = newState;
6708 } else {
6709 // We're dealing with a component level state change
6710 switch (newState) {
6711 case COMPONENT_ENABLED_STATE_ENABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006712 if (!pkgSetting.enableComponentLP(className)) {
6713 return;
6714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 break;
6716 case COMPONENT_ENABLED_STATE_DISABLED:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006717 if (!pkgSetting.disableComponentLP(className)) {
6718 return;
6719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 break;
6721 case COMPONENT_ENABLED_STATE_DEFAULT:
Dianne Hackbornd7c09682010-03-30 10:42:20 -07006722 if (!pkgSetting.restoreComponentLP(className)) {
6723 return;
6724 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 break;
6726 default:
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08006727 Slog.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006728 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 }
6730 }
6731 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006732 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006733 components = mPendingBroadcasts.get(packageName);
6734 boolean newPackage = components == null;
6735 if (newPackage) {
6736 components = new ArrayList<String>();
6737 }
6738 if (!components.contains(componentName)) {
6739 components.add(componentName);
6740 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006741 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
6742 sendNow = true;
6743 // Purge entry from pending broadcast list if another one exists already
6744 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006745 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006746 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006747 if (newPackage) {
6748 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006749 }
6750 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
6751 // Schedule a message
6752 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
6753 }
6754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006755 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 long callingId = Binder.clearCallingIdentity();
6758 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006759 if (sendNow) {
6760 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006761 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 } finally {
6764 Binder.restoreCallingIdentity(callingId);
6765 }
6766 }
6767
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006768 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08006769 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
6770 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
6771 + " components=" + componentNames);
6772 Bundle extras = new Bundle(4);
6773 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
6774 String nameList[] = new String[componentNames.size()];
6775 componentNames.toArray(nameList);
6776 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006777 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
6778 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006779 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07006780 }
6781
Jacek Surazski65e13172009-04-28 15:26:38 +02006782 public String getInstallerPackageName(String packageName) {
6783 synchronized (mPackages) {
6784 PackageSetting pkg = mSettings.mPackages.get(packageName);
6785 if (pkg == null) {
6786 throw new IllegalArgumentException("Unknown package: " + packageName);
6787 }
6788 return pkg.installerPackageName;
6789 }
6790 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006792 public int getApplicationEnabledSetting(String appPackageName) {
6793 synchronized (mPackages) {
6794 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
6795 if (pkg == null) {
6796 throw new IllegalArgumentException("Unknown package: " + appPackageName);
6797 }
6798 return pkg.enabled;
6799 }
6800 }
6801
6802 public int getComponentEnabledSetting(ComponentName componentName) {
6803 synchronized (mPackages) {
6804 final String packageNameStr = componentName.getPackageName();
6805 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
6806 if (pkg == null) {
6807 throw new IllegalArgumentException("Unknown component: " + componentName);
6808 }
6809 final String classNameStr = componentName.getClassName();
6810 return pkg.currentEnabledStateLP(classNameStr);
6811 }
6812 }
6813
6814 public void enterSafeMode() {
6815 if (!mSystemReady) {
6816 mSafeMode = true;
6817 }
6818 }
6819
6820 public void systemReady() {
6821 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006822
6823 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006824 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006825 mContext.getContentResolver(),
6826 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006827 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006828 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006829 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006830 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 }
6832
6833 public boolean isSafeMode() {
6834 return mSafeMode;
6835 }
6836
6837 public boolean hasSystemUidErrors() {
6838 return mHasSystemUidErrors;
6839 }
6840
6841 static String arrayToString(int[] array) {
6842 StringBuffer buf = new StringBuffer(128);
6843 buf.append('[');
6844 if (array != null) {
6845 for (int i=0; i<array.length; i++) {
6846 if (i > 0) buf.append(", ");
6847 buf.append(array[i]);
6848 }
6849 }
6850 buf.append(']');
6851 return buf.toString();
6852 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006854 @Override
6855 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6856 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6857 != PackageManager.PERMISSION_GRANTED) {
6858 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6859 + Binder.getCallingPid()
6860 + ", uid=" + Binder.getCallingUid()
6861 + " without permission "
6862 + android.Manifest.permission.DUMP);
6863 return;
6864 }
6865
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006866 String packageName = null;
6867
6868 int opti = 0;
6869 while (opti < args.length) {
6870 String opt = args[opti];
6871 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') {
6872 break;
6873 }
6874 opti++;
6875 if ("-a".equals(opt)) {
6876 // Right now we only know how to print all.
6877 } else if ("-h".equals(opt)) {
6878 pw.println("Package manager dump options:");
6879 pw.println(" [-h] [cmd] ...");
6880 pw.println(" cmd may be one of:");
6881 pw.println(" [package.name]: info about given package");
6882 return;
6883 } else {
6884 pw.println("Unknown argument: " + opt + "; use -h for help");
6885 }
6886 }
6887
6888 // Is the caller requesting to dump a particular piece of data?
6889 if (opti < args.length) {
6890 String cmd = args[opti];
6891 opti++;
6892 // Is this a package name?
6893 if ("android".equals(cmd) || cmd.contains(".")) {
6894 packageName = cmd;
6895 }
6896 }
6897
6898 boolean printedTitle = false;
6899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 synchronized (mPackages) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006901 if (mActivities.dump(pw, "Activity Resolver Table:", " ", packageName)) {
6902 printedTitle = true;
6903 }
6904 if (mReceivers.dump(pw, printedTitle
6905 ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:",
6906 " ", packageName)) {
6907 printedTitle = true;
6908 }
6909 if (mServices.dump(pw, printedTitle
6910 ? "\nService Resolver Table:" : "Service Resolver Table:",
6911 " ", packageName)) {
6912 printedTitle = true;
6913 }
6914 if (mSettings.mPreferredActivities.dump(pw, printedTitle
6915 ? "\nPreferred Activities:" : "Preferred Activities:",
6916 " ", packageName)) {
6917 printedTitle = true;
6918 }
6919 boolean printedSomething = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 {
6921 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006922 if (packageName != null && !packageName.equals(p.sourcePackage)) {
6923 continue;
6924 }
6925 if (!printedSomething) {
6926 if (printedTitle) pw.println(" ");
6927 pw.println("Permissions:");
6928 printedSomething = true;
6929 printedTitle = true;
6930 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006931 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
6932 pw.print(Integer.toHexString(System.identityHashCode(p)));
6933 pw.println("):");
6934 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
6935 pw.print(" uid="); pw.print(p.uid);
6936 pw.print(" gids="); pw.print(arrayToString(p.gids));
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006937 pw.print(" type="); pw.print(p.type);
6938 pw.print(" prot="); pw.println(p.protectionLevel);
6939 if (p.packageSetting != null) {
6940 pw.print(" packageSetting="); pw.println(p.packageSetting);
6941 }
6942 if (p.perm != null) {
6943 pw.print(" perm="); pw.println(p.perm);
6944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 }
6946 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006947 printedSomething = false;
6948 SharedUserSetting packageSharedUser = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 {
6950 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07006951 if (packageName != null && !packageName.equals(ps.realName)
6952 && !packageName.equals(ps.name)) {
6953 continue;
6954 }
6955 if (!printedSomething) {
6956 if (printedTitle) pw.println(" ");
6957 pw.println("Packages:");
6958 printedSomething = true;
6959 printedTitle = true;
6960 }
6961 packageSharedUser = ps.sharedUser;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006962 pw.print(" Package [");
6963 pw.print(ps.realName != null ? ps.realName : ps.name);
6964 pw.print("] (");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006965 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6966 pw.println("):");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08006967 if (ps.realName != null) {
6968 pw.print(" compat name="); pw.println(ps.name);
6969 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006970 pw.print(" userId="); pw.print(ps.userId);
6971 pw.print(" gids="); pw.println(arrayToString(ps.gids));
6972 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6973 pw.print(" pkg="); pw.println(ps.pkg);
6974 pw.print(" codePath="); pw.println(ps.codePathString);
6975 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006977 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006978 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006979 pw.print(" supportsScreens=[");
6980 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006981 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006982 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006983 if (!first) pw.print(", ");
6984 first = false;
6985 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006986 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006987 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006988 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006989 if (!first) pw.print(", ");
6990 first = false;
6991 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006992 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006993 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006994 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006995 if (!first) pw.print(", ");
6996 first = false;
6997 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006998 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006999 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007000 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007001 if (!first) pw.print(", ");
7002 first = false;
7003 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07007004 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007005 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007006 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
7007 if (!first) pw.print(", ");
7008 first = false;
7009 pw.print("anyDensity");
7010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07007012 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007013 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
7014 pw.print(" signatures="); pw.println(ps.signatures);
7015 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007016 pw.print(" haveGids="); pw.println(ps.haveGids);
7017 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007018 pw.print(" installStatus="); pw.print(ps.installStatus);
7019 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007020 if (ps.disabledComponents.size() > 0) {
7021 pw.println(" disabledComponents:");
7022 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007023 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 }
7025 }
7026 if (ps.enabledComponents.size() > 0) {
7027 pw.println(" enabledComponents:");
7028 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007029 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007030 }
7031 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007032 if (ps.grantedPermissions.size() > 0) {
7033 pw.println(" grantedPermissions:");
7034 for (String s : ps.grantedPermissions) {
7035 pw.print(" "); pw.println(s);
7036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007037 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007038 }
7039 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007040 printedSomething = false;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007041 if (mSettings.mRenamedPackages.size() > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007042 for (HashMap.Entry<String, String> e
7043 : mSettings.mRenamedPackages.entrySet()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007044 if (packageName != null && !packageName.equals(e.getKey())
7045 && !packageName.equals(e.getValue())) {
7046 continue;
7047 }
7048 if (!printedSomething) {
7049 if (printedTitle) pw.println(" ");
7050 pw.println("Renamed packages:");
7051 printedSomething = true;
7052 printedTitle = true;
7053 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007054 pw.print(" "); pw.print(e.getKey()); pw.print(" -> ");
7055 pw.println(e.getValue());
7056 }
7057 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007058 printedSomething = false;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007059 if (mSettings.mDisabledSysPackages.size() > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007060 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007061 if (packageName != null && !packageName.equals(ps.realName)
7062 && !packageName.equals(ps.name)) {
7063 continue;
7064 }
7065 if (!printedSomething) {
7066 if (printedTitle) pw.println(" ");
7067 pw.println("Hidden system packages:");
7068 printedSomething = true;
7069 printedTitle = true;
7070 }
7071 pw.print(" Package [");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007072 pw.print(ps.realName != null ? ps.realName : ps.name);
7073 pw.print("] (");
7074 pw.print(Integer.toHexString(System.identityHashCode(ps)));
7075 pw.println("):");
7076 if (ps.realName != null) {
7077 pw.print(" compat name="); pw.println(ps.name);
7078 }
7079 pw.print(" userId="); pw.println(ps.userId);
7080 pw.print(" sharedUser="); pw.println(ps.sharedUser);
7081 pw.print(" codePath="); pw.println(ps.codePathString);
7082 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
7083 }
7084 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007085 printedSomething = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007086 {
7087 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007088 if (packageName != null && su != packageSharedUser) {
7089 continue;
7090 }
7091 if (!printedSomething) {
7092 if (printedTitle) pw.println(" ");
7093 pw.println("Shared users:");
7094 printedSomething = true;
7095 printedTitle = true;
7096 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007097 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
7098 pw.print(Integer.toHexString(System.identityHashCode(su)));
7099 pw.println("):");
7100 pw.print(" userId="); pw.print(su.userId);
7101 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007102 pw.println(" grantedPermissions:");
7103 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007104 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007105 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007106 }
7107 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007108
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007109 if (packageName == null) {
7110 if (printedTitle) pw.println(" ");
7111 printedTitle = true;
7112 pw.println("Settings parse messages:");
7113 pw.println(mSettings.mReadMessages.toString());
7114
7115 pw.println(" ");
7116 pw.println("Package warning messages:");
7117 File fname = getSettingsProblemFile();
7118 FileInputStream in;
7119 try {
7120 in = new FileInputStream(fname);
7121 int avail = in.available();
7122 byte[] data = new byte[avail];
7123 in.read(data);
7124 pw.println(new String(data));
7125 } catch (FileNotFoundException e) {
7126 } catch (IOException e) {
7127 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007129 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05007130
7131 synchronized (mProviders) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007132 boolean printedSomething = false;
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05007133 for (PackageParser.Provider p : mProviders.values()) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007134 if (packageName != null && !packageName.equals(p.info.packageName)) {
7135 continue;
7136 }
7137 if (!printedSomething) {
7138 if (printedTitle) pw.println(" ");
7139 pw.println("Registered ContentProviders:");
7140 printedSomething = true;
7141 printedTitle = true;
7142 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007143 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05007144 pw.println(p.toString());
7145 }
7146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007147 }
7148
7149 static final class BasePermission {
7150 final static int TYPE_NORMAL = 0;
7151 final static int TYPE_BUILTIN = 1;
7152 final static int TYPE_DYNAMIC = 2;
7153
7154 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007155 String sourcePackage;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007156 PackageSettingBase packageSetting;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 final int type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007158 int protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007159 PackageParser.Permission perm;
7160 PermissionInfo pendingInfo;
7161 int uid;
7162 int[] gids;
7163
7164 BasePermission(String _name, String _sourcePackage, int _type) {
7165 name = _name;
7166 sourcePackage = _sourcePackage;
7167 type = _type;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007168 // Default to most conservative protection level.
7169 protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
7170 }
7171
7172 public String toString() {
7173 return "BasePermission{"
7174 + Integer.toHexString(System.identityHashCode(this))
7175 + " " + name + "}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007176 }
7177 }
7178
7179 static class PackageSignatures {
7180 private Signature[] mSignatures;
7181
7182 PackageSignatures(Signature[] sigs) {
7183 assignSignatures(sigs);
7184 }
7185
7186 PackageSignatures() {
7187 }
7188
7189 void writeXml(XmlSerializer serializer, String tagName,
7190 ArrayList<Signature> pastSignatures) throws IOException {
7191 if (mSignatures == null) {
7192 return;
7193 }
7194 serializer.startTag(null, tagName);
7195 serializer.attribute(null, "count",
7196 Integer.toString(mSignatures.length));
7197 for (int i=0; i<mSignatures.length; i++) {
7198 serializer.startTag(null, "cert");
7199 final Signature sig = mSignatures[i];
7200 final int sigHash = sig.hashCode();
7201 final int numPast = pastSignatures.size();
7202 int j;
7203 for (j=0; j<numPast; j++) {
7204 Signature pastSig = pastSignatures.get(j);
7205 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
7206 serializer.attribute(null, "index", Integer.toString(j));
7207 break;
7208 }
7209 }
7210 if (j >= numPast) {
7211 pastSignatures.add(sig);
7212 serializer.attribute(null, "index", Integer.toString(numPast));
7213 serializer.attribute(null, "key", sig.toCharsString());
7214 }
7215 serializer.endTag(null, "cert");
7216 }
7217 serializer.endTag(null, tagName);
7218 }
7219
7220 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
7221 throws IOException, XmlPullParserException {
7222 String countStr = parser.getAttributeValue(null, "count");
7223 if (countStr == null) {
7224 reportSettingsProblem(Log.WARN,
7225 "Error in package manager settings: <signatures> has"
7226 + " no count at " + parser.getPositionDescription());
7227 XmlUtils.skipCurrentTag(parser);
7228 }
7229 final int count = Integer.parseInt(countStr);
7230 mSignatures = new Signature[count];
7231 int pos = 0;
7232
7233 int outerDepth = parser.getDepth();
7234 int type;
7235 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7236 && (type != XmlPullParser.END_TAG
7237 || parser.getDepth() > outerDepth)) {
7238 if (type == XmlPullParser.END_TAG
7239 || type == XmlPullParser.TEXT) {
7240 continue;
7241 }
7242
7243 String tagName = parser.getName();
7244 if (tagName.equals("cert")) {
7245 if (pos < count) {
7246 String index = parser.getAttributeValue(null, "index");
7247 if (index != null) {
7248 try {
7249 int idx = Integer.parseInt(index);
7250 String key = parser.getAttributeValue(null, "key");
7251 if (key == null) {
7252 if (idx >= 0 && idx < pastSignatures.size()) {
7253 Signature sig = pastSignatures.get(idx);
7254 if (sig != null) {
7255 mSignatures[pos] = pastSignatures.get(idx);
7256 pos++;
7257 } else {
7258 reportSettingsProblem(Log.WARN,
7259 "Error in package manager settings: <cert> "
7260 + "index " + index + " is not defined at "
7261 + parser.getPositionDescription());
7262 }
7263 } else {
7264 reportSettingsProblem(Log.WARN,
7265 "Error in package manager settings: <cert> "
7266 + "index " + index + " is out of bounds at "
7267 + parser.getPositionDescription());
7268 }
7269 } else {
7270 while (pastSignatures.size() <= idx) {
7271 pastSignatures.add(null);
7272 }
7273 Signature sig = new Signature(key);
7274 pastSignatures.set(idx, sig);
7275 mSignatures[pos] = sig;
7276 pos++;
7277 }
7278 } catch (NumberFormatException e) {
7279 reportSettingsProblem(Log.WARN,
7280 "Error in package manager settings: <cert> "
7281 + "index " + index + " is not a number at "
7282 + parser.getPositionDescription());
7283 }
7284 } else {
7285 reportSettingsProblem(Log.WARN,
7286 "Error in package manager settings: <cert> has"
7287 + " no index at " + parser.getPositionDescription());
7288 }
7289 } else {
7290 reportSettingsProblem(Log.WARN,
7291 "Error in package manager settings: too "
7292 + "many <cert> tags, expected " + count
7293 + " at " + parser.getPositionDescription());
7294 }
7295 } else {
7296 reportSettingsProblem(Log.WARN,
7297 "Unknown element under <cert>: "
7298 + parser.getName());
7299 }
7300 XmlUtils.skipCurrentTag(parser);
7301 }
7302
7303 if (pos < count) {
7304 // Should never happen -- there is an error in the written
7305 // settings -- but if it does we don't want to generate
7306 // a bad array.
7307 Signature[] newSigs = new Signature[pos];
7308 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
7309 mSignatures = newSigs;
7310 }
7311 }
7312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007313 private void assignSignatures(Signature[] sigs) {
7314 if (sigs == null) {
7315 mSignatures = null;
7316 return;
7317 }
7318 mSignatures = new Signature[sigs.length];
7319 for (int i=0; i<sigs.length; i++) {
7320 mSignatures[i] = sigs[i];
7321 }
7322 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 @Override
7325 public String toString() {
7326 StringBuffer buf = new StringBuffer(128);
7327 buf.append("PackageSignatures{");
7328 buf.append(Integer.toHexString(System.identityHashCode(this)));
7329 buf.append(" [");
7330 if (mSignatures != null) {
7331 for (int i=0; i<mSignatures.length; i++) {
7332 if (i > 0) buf.append(", ");
7333 buf.append(Integer.toHexString(
7334 System.identityHashCode(mSignatures[i])));
7335 }
7336 }
7337 buf.append("]}");
7338 return buf.toString();
7339 }
7340 }
7341
7342 static class PreferredActivity extends IntentFilter {
7343 final int mMatch;
7344 final String[] mSetPackages;
7345 final String[] mSetClasses;
7346 final String[] mSetComponents;
7347 final ComponentName mActivity;
7348 final String mShortActivity;
7349 String mParseError;
7350
7351 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
7352 ComponentName activity) {
7353 super(filter);
7354 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
7355 mActivity = activity;
7356 mShortActivity = activity.flattenToShortString();
7357 mParseError = null;
7358 if (set != null) {
7359 final int N = set.length;
7360 String[] myPackages = new String[N];
7361 String[] myClasses = new String[N];
7362 String[] myComponents = new String[N];
7363 for (int i=0; i<N; i++) {
7364 ComponentName cn = set[i];
7365 if (cn == null) {
7366 mSetPackages = null;
7367 mSetClasses = null;
7368 mSetComponents = null;
7369 return;
7370 }
7371 myPackages[i] = cn.getPackageName().intern();
7372 myClasses[i] = cn.getClassName().intern();
7373 myComponents[i] = cn.flattenToShortString().intern();
7374 }
7375 mSetPackages = myPackages;
7376 mSetClasses = myClasses;
7377 mSetComponents = myComponents;
7378 } else {
7379 mSetPackages = null;
7380 mSetClasses = null;
7381 mSetComponents = null;
7382 }
7383 }
7384
7385 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
7386 IOException {
7387 mShortActivity = parser.getAttributeValue(null, "name");
7388 mActivity = ComponentName.unflattenFromString(mShortActivity);
7389 if (mActivity == null) {
7390 mParseError = "Bad activity name " + mShortActivity;
7391 }
7392 String matchStr = parser.getAttributeValue(null, "match");
7393 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
7394 String setCountStr = parser.getAttributeValue(null, "set");
7395 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
7396
7397 String[] myPackages = setCount > 0 ? new String[setCount] : null;
7398 String[] myClasses = setCount > 0 ? new String[setCount] : null;
7399 String[] myComponents = setCount > 0 ? new String[setCount] : null;
7400
7401 int setPos = 0;
7402
7403 int outerDepth = parser.getDepth();
7404 int type;
7405 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7406 && (type != XmlPullParser.END_TAG
7407 || parser.getDepth() > outerDepth)) {
7408 if (type == XmlPullParser.END_TAG
7409 || type == XmlPullParser.TEXT) {
7410 continue;
7411 }
7412
7413 String tagName = parser.getName();
7414 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
7415 // + parser.getDepth() + " tag=" + tagName);
7416 if (tagName.equals("set")) {
7417 String name = parser.getAttributeValue(null, "name");
7418 if (name == null) {
7419 if (mParseError == null) {
7420 mParseError = "No name in set tag in preferred activity "
7421 + mShortActivity;
7422 }
7423 } else if (setPos >= setCount) {
7424 if (mParseError == null) {
7425 mParseError = "Too many set tags in preferred activity "
7426 + mShortActivity;
7427 }
7428 } else {
7429 ComponentName cn = ComponentName.unflattenFromString(name);
7430 if (cn == null) {
7431 if (mParseError == null) {
7432 mParseError = "Bad set name " + name + " in preferred activity "
7433 + mShortActivity;
7434 }
7435 } else {
7436 myPackages[setPos] = cn.getPackageName();
7437 myClasses[setPos] = cn.getClassName();
7438 myComponents[setPos] = name;
7439 setPos++;
7440 }
7441 }
7442 XmlUtils.skipCurrentTag(parser);
7443 } else if (tagName.equals("filter")) {
7444 //Log.i(TAG, "Starting to parse filter...");
7445 readFromXml(parser);
7446 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
7447 // + parser.getDepth() + " tag=" + parser.getName());
7448 } else {
7449 reportSettingsProblem(Log.WARN,
7450 "Unknown element under <preferred-activities>: "
7451 + parser.getName());
7452 XmlUtils.skipCurrentTag(parser);
7453 }
7454 }
7455
7456 if (setPos != setCount) {
7457 if (mParseError == null) {
7458 mParseError = "Not enough set tags (expected " + setCount
7459 + " but found " + setPos + ") in " + mShortActivity;
7460 }
7461 }
7462
7463 mSetPackages = myPackages;
7464 mSetClasses = myClasses;
7465 mSetComponents = myComponents;
7466 }
7467
7468 public void writeToXml(XmlSerializer serializer) throws IOException {
7469 final int NS = mSetClasses != null ? mSetClasses.length : 0;
7470 serializer.attribute(null, "name", mShortActivity);
7471 serializer.attribute(null, "match", Integer.toHexString(mMatch));
7472 serializer.attribute(null, "set", Integer.toString(NS));
7473 for (int s=0; s<NS; s++) {
7474 serializer.startTag(null, "set");
7475 serializer.attribute(null, "name", mSetComponents[s]);
7476 serializer.endTag(null, "set");
7477 }
7478 serializer.startTag(null, "filter");
7479 super.writeToXml(serializer);
7480 serializer.endTag(null, "filter");
7481 }
7482
7483 boolean sameSet(List<ResolveInfo> query, int priority) {
7484 if (mSetPackages == null) return false;
7485 final int NQ = query.size();
7486 final int NS = mSetPackages.length;
7487 int numMatch = 0;
7488 for (int i=0; i<NQ; i++) {
7489 ResolveInfo ri = query.get(i);
7490 if (ri.priority != priority) continue;
7491 ActivityInfo ai = ri.activityInfo;
7492 boolean good = false;
7493 for (int j=0; j<NS; j++) {
7494 if (mSetPackages[j].equals(ai.packageName)
7495 && mSetClasses[j].equals(ai.name)) {
7496 numMatch++;
7497 good = true;
7498 break;
7499 }
7500 }
7501 if (!good) return false;
7502 }
7503 return numMatch == NS;
7504 }
7505 }
7506
7507 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007508 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 HashSet<String> grantedPermissions = new HashSet<String>();
7511 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007513 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08007514 setFlags(pkgFlags);
7515 }
7516
7517 void setFlags(int pkgFlags) {
Jeff Brown07330792010-03-30 19:57:08 -07007518 this.pkgFlags = pkgFlags & (
7519 ApplicationInfo.FLAG_SYSTEM |
7520 ApplicationInfo.FLAG_FORWARD_LOCK |
7521 ApplicationInfo.FLAG_EXTERNAL_STORAGE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007522 }
7523 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007525 /**
7526 * Settings base class for pending and resolved classes.
7527 */
7528 static class PackageSettingBase extends GrantedPermissions {
7529 final String name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007530 final String realName;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007531 File codePath;
7532 String codePathString;
7533 File resourcePath;
7534 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 private long timeStamp;
7536 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007537 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007539 boolean uidError;
7540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 PackageSignatures signatures = new PackageSignatures();
7542
7543 boolean permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007544 boolean haveGids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 /* Explicitly disabled components */
7547 HashSet<String> disabledComponents = new HashSet<String>(0);
7548 /* Explicitly enabled components */
7549 HashSet<String> enabledComponents = new HashSet<String>(0);
7550 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7551 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007552
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007553 PackageSettingBase origPackage;
7554
Jacek Surazski65e13172009-04-28 15:26:38 +02007555 /* package name of the app that installed this package */
7556 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007557
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007558 PackageSettingBase(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007559 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007560 super(pkgFlags);
7561 this.name = name;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007562 this.realName = realName;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007563 init(codePath, resourcePath, pVersionCode);
7564 }
7565
7566 void init(File codePath, File resourcePath, int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567 this.codePath = codePath;
7568 this.codePathString = codePath.toString();
7569 this.resourcePath = resourcePath;
7570 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007571 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007572 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007573
Jacek Surazski65e13172009-04-28 15:26:38 +02007574 public void setInstallerPackageName(String packageName) {
7575 installerPackageName = packageName;
7576 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007577
Jacek Surazski65e13172009-04-28 15:26:38 +02007578 String getInstallerPackageName() {
7579 return installerPackageName;
7580 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 public void setInstallStatus(int newStatus) {
7583 installStatus = newStatus;
7584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 public int getInstallStatus() {
7587 return installStatus;
7588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 public void setTimeStamp(long newStamp) {
7591 if (newStamp != timeStamp) {
7592 timeStamp = newStamp;
7593 timeStampString = Long.toString(newStamp);
7594 }
7595 }
7596
7597 public void setTimeStamp(long newStamp, String newStampStr) {
7598 timeStamp = newStamp;
7599 timeStampString = newStampStr;
7600 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007602 public long getTimeStamp() {
7603 return timeStamp;
7604 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 public String getTimeStampStr() {
7607 return timeStampString;
7608 }
7609
7610 public void copyFrom(PackageSettingBase base) {
7611 grantedPermissions = base.grantedPermissions;
7612 gids = base.gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 timeStamp = base.timeStamp;
7615 timeStampString = base.timeStampString;
7616 signatures = base.signatures;
7617 permissionsFixed = base.permissionsFixed;
Dianne Hackbornbbfd58a2010-03-23 11:49:59 -07007618 haveGids = base.haveGids;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007619 disabledComponents = base.disabledComponents;
7620 enabledComponents = base.enabledComponents;
7621 enabled = base.enabled;
7622 installStatus = base.installStatus;
7623 }
7624
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007625 boolean enableComponentLP(String componentClassName) {
7626 boolean changed = disabledComponents.remove(componentClassName);
7627 changed |= enabledComponents.add(componentClassName);
7628 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007629 }
7630
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007631 boolean disableComponentLP(String componentClassName) {
7632 boolean changed = enabledComponents.remove(componentClassName);
7633 changed |= disabledComponents.add(componentClassName);
7634 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 }
7636
Dianne Hackbornd7c09682010-03-30 10:42:20 -07007637 boolean restoreComponentLP(String componentClassName) {
7638 boolean changed = enabledComponents.remove(componentClassName);
7639 changed |= disabledComponents.remove(componentClassName);
7640 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 }
7642
7643 int currentEnabledStateLP(String componentName) {
7644 if (enabledComponents.contains(componentName)) {
7645 return COMPONENT_ENABLED_STATE_ENABLED;
7646 } else if (disabledComponents.contains(componentName)) {
7647 return COMPONENT_ENABLED_STATE_DISABLED;
7648 } else {
7649 return COMPONENT_ENABLED_STATE_DEFAULT;
7650 }
7651 }
7652 }
7653
7654 /**
7655 * Settings data for a particular package we know about.
7656 */
7657 static final class PackageSetting extends PackageSettingBase {
7658 int userId;
7659 PackageParser.Package pkg;
7660 SharedUserSetting sharedUser;
7661
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007662 PackageSetting(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007663 int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007664 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007665 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 @Override
7668 public String toString() {
7669 return "PackageSetting{"
7670 + Integer.toHexString(System.identityHashCode(this))
7671 + " " + name + "/" + userId + "}";
7672 }
7673 }
7674
7675 /**
7676 * Settings data for a particular shared user ID we know about.
7677 */
7678 static final class SharedUserSetting extends GrantedPermissions {
7679 final String name;
7680 int userId;
7681 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
7682 final PackageSignatures signatures = new PackageSignatures();
7683
7684 SharedUserSetting(String _name, int _pkgFlags) {
7685 super(_pkgFlags);
7686 name = _name;
7687 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 @Override
7690 public String toString() {
7691 return "SharedUserSetting{"
7692 + Integer.toHexString(System.identityHashCode(this))
7693 + " " + name + "/" + userId + "}";
7694 }
7695 }
7696
7697 /**
7698 * Holds information about dynamic settings.
7699 */
7700 private static final class Settings {
7701 private final File mSettingsFilename;
7702 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007703 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007704 private final HashMap<String, PackageSetting> mPackages =
7705 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007706 // List of replaced system applications
7707 final HashMap<String, PackageSetting> mDisabledSysPackages =
7708 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007710 // The user's preferred activities associated with particular intent
7711 // filters.
7712 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
7713 new IntentResolver<PreferredActivity, PreferredActivity>() {
7714 @Override
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007715 protected String packageForFilter(PreferredActivity filter) {
7716 return filter.mActivity.getPackageName();
7717 }
7718 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007719 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007720 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007721 out.print(prefix); out.print(
7722 Integer.toHexString(System.identityHashCode(filter)));
7723 out.print(' ');
7724 out.print(filter.mActivity.flattenToShortString());
7725 out.print(" match=0x");
7726 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007728 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007729 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007730 out.print(prefix); out.print(" ");
7731 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007732 }
7733 }
7734 }
7735 };
7736 private final HashMap<String, SharedUserSetting> mSharedUsers =
7737 new HashMap<String, SharedUserSetting>();
7738 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
7739 private final SparseArray<Object> mOtherUserIds =
7740 new SparseArray<Object>();
7741
7742 // For reading/writing settings file.
7743 private final ArrayList<Signature> mPastSignatures =
7744 new ArrayList<Signature>();
7745
7746 // Mapping from permission names to info about them.
7747 final HashMap<String, BasePermission> mPermissions =
7748 new HashMap<String, BasePermission>();
7749
7750 // Mapping from permission tree names to info about them.
7751 final HashMap<String, BasePermission> mPermissionTrees =
7752 new HashMap<String, BasePermission>();
7753
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007754 // Packages that have been uninstalled and still need their external
7755 // storage data deleted.
7756 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
7757
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007758 // Packages that have been renamed since they were first installed.
7759 // Keys are the new names of the packages, values are the original
7760 // names. The packages appear everwhere else under their original
7761 // names.
7762 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
7763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 private final StringBuilder mReadMessages = new StringBuilder();
7765
7766 private static final class PendingPackage extends PackageSettingBase {
7767 final int sharedId;
7768
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007769 PendingPackage(String name, String realName, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007770 int sharedId, int pVersionCode, int pkgFlags) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007771 super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007772 this.sharedId = sharedId;
7773 }
7774 }
7775 private final ArrayList<PendingPackage> mPendingPackages
7776 = new ArrayList<PendingPackage>();
7777
7778 Settings() {
7779 File dataDir = Environment.getDataDirectory();
7780 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08007781 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007782 systemDir.mkdirs();
7783 FileUtils.setPermissions(systemDir.toString(),
7784 FileUtils.S_IRWXU|FileUtils.S_IRWXG
7785 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
7786 -1, -1);
7787 mSettingsFilename = new File(systemDir, "packages.xml");
7788 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007789 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007790 }
7791
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007792 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007793 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 int pkgFlags, boolean create, boolean add) {
7795 final String name = pkg.packageName;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007796 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007797 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 return p;
7799 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007800
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007801 PackageSetting peekPackageLP(String name) {
7802 return mPackages.get(name);
7803 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007804 PackageSetting p = mPackages.get(name);
7805 if (p != null && p.codePath.getPath().equals(codePath)) {
7806 return p;
7807 }
7808 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007809 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007812 void setInstallStatus(String pkgName, int status) {
7813 PackageSetting p = mPackages.get(pkgName);
7814 if(p != null) {
7815 if(p.getInstallStatus() != status) {
7816 p.setInstallStatus(status);
7817 }
7818 }
7819 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007820
Jacek Surazski65e13172009-04-28 15:26:38 +02007821 void setInstallerPackageName(String pkgName,
7822 String installerPkgName) {
7823 PackageSetting p = mPackages.get(pkgName);
7824 if(p != null) {
7825 p.setInstallerPackageName(installerPkgName);
7826 }
7827 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007828
Jacek Surazski65e13172009-04-28 15:26:38 +02007829 String getInstallerPackageName(String pkgName) {
7830 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007831 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02007832 }
7833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007834 int getInstallStatus(String pkgName) {
7835 PackageSetting p = mPackages.get(pkgName);
7836 if(p != null) {
7837 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007839 return -1;
7840 }
7841
7842 SharedUserSetting getSharedUserLP(String name,
7843 int pkgFlags, boolean create) {
7844 SharedUserSetting s = mSharedUsers.get(name);
7845 if (s == null) {
7846 if (!create) {
7847 return null;
7848 }
7849 s = new SharedUserSetting(name, pkgFlags);
7850 if (MULTIPLE_APPLICATION_UIDS) {
7851 s.userId = newUserIdLP(s);
7852 } else {
7853 s.userId = FIRST_APPLICATION_UID;
7854 }
7855 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
7856 // < 0 means we couldn't assign a userid; fall out and return
7857 // s, which is currently null
7858 if (s.userId >= 0) {
7859 mSharedUsers.put(name, s);
7860 }
7861 }
7862
7863 return s;
7864 }
7865
7866 int disableSystemPackageLP(String name) {
7867 PackageSetting p = mPackages.get(name);
7868 if(p == null) {
7869 Log.w(TAG, "Package:"+name+" is not an installed package");
7870 return -1;
7871 }
7872 PackageSetting dp = mDisabledSysPackages.get(name);
7873 // always make sure the system package code and resource paths dont change
7874 if(dp == null) {
7875 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7876 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7877 }
7878 mDisabledSysPackages.put(name, p);
7879 }
7880 return removePackageLP(name);
7881 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007883 PackageSetting enableSystemPackageLP(String name) {
7884 PackageSetting p = mDisabledSysPackages.get(name);
7885 if(p == null) {
7886 Log.w(TAG, "Package:"+name+" is not disabled");
7887 return null;
7888 }
7889 // Reset flag in ApplicationInfo object
7890 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7891 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7892 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007893 PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007894 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 mDisabledSysPackages.remove(name);
7896 return ret;
7897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007898
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007899 PackageSetting addPackageLP(String name, String realName, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007900 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007901 PackageSetting p = mPackages.get(name);
7902 if (p != null) {
7903 if (p.userId == uid) {
7904 return p;
7905 }
7906 reportSettingsProblem(Log.ERROR,
7907 "Adding duplicate package, keeping first: " + name);
7908 return null;
7909 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007910 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 p.userId = uid;
7912 if (addUserIdLP(uid, p, name)) {
7913 mPackages.put(name, p);
7914 return p;
7915 }
7916 return null;
7917 }
7918
7919 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
7920 SharedUserSetting s = mSharedUsers.get(name);
7921 if (s != null) {
7922 if (s.userId == uid) {
7923 return s;
7924 }
7925 reportSettingsProblem(Log.ERROR,
7926 "Adding duplicate shared user, keeping first: " + name);
7927 return null;
7928 }
7929 s = new SharedUserSetting(name, pkgFlags);
7930 s.userId = uid;
7931 if (addUserIdLP(uid, s, name)) {
7932 mSharedUsers.put(name, s);
7933 return s;
7934 }
7935 return null;
7936 }
7937
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007938 // Transfer ownership of permissions from one package to another.
7939 private void transferPermissions(String origPkg, String newPkg) {
7940 // Transfer ownership of permissions to the new package.
7941 for (int i=0; i<2; i++) {
7942 HashMap<String, BasePermission> permissions =
7943 i == 0 ? mPermissionTrees : mPermissions;
7944 for (BasePermission bp : permissions.values()) {
7945 if (origPkg.equals(bp.sourcePackage)) {
7946 if (DEBUG_UPGRADE) Log.v(TAG,
7947 "Moving permission " + bp.name
7948 + " from pkg " + bp.sourcePackage
7949 + " to " + newPkg);
7950 bp.sourcePackage = newPkg;
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007951 bp.packageSetting = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007952 bp.perm = null;
7953 if (bp.pendingInfo != null) {
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07007954 bp.pendingInfo.packageName = newPkg;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007955 }
7956 bp.uid = 0;
7957 bp.gids = null;
7958 }
7959 }
7960 }
7961 }
7962
7963 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08007964 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007965 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007966 PackageSetting p = mPackages.get(name);
7967 if (p != null) {
7968 if (!p.codePath.equals(codePath)) {
7969 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007970 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007971 // This is an updated system app with versions in both system
7972 // and data partition. Just let the most recent version
7973 // take precedence.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007974 Slog.w(TAG, "Trying to update system app code path from " +
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007975 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007976 } else {
Dianne Hackborn9e0f5d92010-02-22 15:05:42 -08007977 // Just a change in the code path is not an issue, but
7978 // let's log a message about it.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08007979 Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007980 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007982 }
7983 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 reportSettingsProblem(Log.WARN,
7985 "Package " + name + " shared user changed from "
7986 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
7987 + " to "
7988 + (sharedUser != null ? sharedUser.name : "<nothing>")
7989 + "; replacing with new");
7990 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007991 } else {
7992 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7993 // If what we are scanning is a system package, then
7994 // make it so, regardless of whether it was previously
7995 // installed only in the data partition.
7996 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 }
7999 }
8000 if (p == null) {
8001 // Create a new PackageSettings entry. this can end up here because
8002 // of code path mismatch or user id mismatch of an updated system partition
8003 if (!create) {
8004 return null;
8005 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008006 if (origPackage != null) {
8007 // We are consuming the data from an existing package.
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008008 p = new PackageSetting(origPackage.name, name, codePath,
8009 resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008010 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
8011 + " is adopting original package " + origPackage.name);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008012 // Note that we will retain the new package's signature so
8013 // that we can keep its data.
8014 PackageSignatures s = p.signatures;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008015 p.copyFrom(origPackage);
Dianne Hackborn4b450412010-03-11 16:20:08 -08008016 p.signatures = s;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008017 p.sharedUser = origPackage.sharedUser;
8018 p.userId = origPackage.userId;
8019 p.origPackage = origPackage;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008020 mRenamedPackages.put(name, origPackage.name);
8021 name = origPackage.name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008022 // Update new package state.
8023 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 } else {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008025 p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008026 p.setTimeStamp(codePath.lastModified());
8027 p.sharedUser = sharedUser;
8028 if (sharedUser != null) {
8029 p.userId = sharedUser.userId;
8030 } else if (MULTIPLE_APPLICATION_UIDS) {
8031 // Clone the setting here for disabled system packages
8032 PackageSetting dis = mDisabledSysPackages.get(name);
8033 if (dis != null) {
8034 // For disabled packages a new setting is created
8035 // from the existing user id. This still has to be
8036 // added to list of user id's
8037 // Copy signatures from previous setting
8038 if (dis.signatures.mSignatures != null) {
8039 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
8040 }
8041 p.userId = dis.userId;
8042 // Clone permissions
8043 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008044 // Clone component info
8045 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
8046 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
8047 // Add new setting to list of user ids
8048 addUserIdLP(p.userId, p, name);
8049 } else {
8050 // Assign new user id
8051 p.userId = newUserIdLP(p);
8052 }
8053 } else {
8054 p.userId = FIRST_APPLICATION_UID;
8055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056 }
8057 if (p.userId < 0) {
8058 reportSettingsProblem(Log.WARN,
8059 "Package " + name + " could not be assigned a valid uid");
8060 return null;
8061 }
8062 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008063 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008064 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008065 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008066 }
8067 }
8068 return p;
8069 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008070
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008071 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008072 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008073 String codePath = pkg.applicationInfo.sourceDir;
8074 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008075 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008076 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008077 Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008078 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008079 p.codePath = new File(codePath);
8080 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008081 }
8082 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008083 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008084 Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07008085 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008086 p.resourcePath = new File(resourcePath);
8087 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008088 }
8089 // Update version code if needed
8090 if (pkg.mVersionCode != p.versionCode) {
8091 p.versionCode = pkg.mVersionCode;
8092 }
Suchi Amalapurapuae181712010-03-30 14:01:02 -07008093 // Update signatures if needed.
8094 if (p.signatures.mSignatures == null) {
8095 p.signatures.assignSignatures(pkg.mSignatures);
8096 }
8097 // If this app defines a shared user id initialize
8098 // the shared user signatures as well.
8099 if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
8100 p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
8101 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008102 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
8103 }
8104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008105 // Utility method that adds a PackageSetting to mPackages and
8106 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008107 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008108 SharedUserSetting sharedUser) {
8109 mPackages.put(name, p);
8110 if (sharedUser != null) {
8111 if (p.sharedUser != null && p.sharedUser != sharedUser) {
8112 reportSettingsProblem(Log.ERROR,
8113 "Package " + p.name + " was user "
8114 + p.sharedUser + " but is now " + sharedUser
8115 + "; I am not changing its files so it will probably fail!");
8116 p.sharedUser.packages.remove(p);
8117 } else if (p.userId != sharedUser.userId) {
8118 reportSettingsProblem(Log.ERROR,
8119 "Package " + p.name + " was user id " + p.userId
8120 + " but is now user " + sharedUser
8121 + " with id " + sharedUser.userId
8122 + "; I am not changing its files so it will probably fail!");
8123 }
8124
8125 sharedUser.packages.add(p);
8126 p.sharedUser = sharedUser;
8127 p.userId = sharedUser.userId;
8128 }
8129 }
8130
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008131 /*
8132 * Update the shared user setting when a package using
8133 * specifying the shared user id is removed. The gids
8134 * associated with each permission of the deleted package
8135 * are removed from the shared user's gid list only if its
8136 * not in use by other permissions of packages in the
8137 * shared user setting.
8138 */
8139 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008141 Slog.i(TAG, "Trying to update info for null package. Just ignoring");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008142 return;
8143 }
8144 // No sharedUserId
8145 if (deletedPs.sharedUser == null) {
8146 return;
8147 }
8148 SharedUserSetting sus = deletedPs.sharedUser;
8149 // Update permissions
8150 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
8151 boolean used = false;
8152 if (!sus.grantedPermissions.contains (eachPerm)) {
8153 continue;
8154 }
8155 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008156 if (pkg.pkg != null &&
Dianne Hackbornf657b632010-03-22 18:08:07 -07008157 !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) &&
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008158 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008159 used = true;
8160 break;
8161 }
8162 }
8163 if (!used) {
8164 // can safely delete this permission from list
8165 sus.grantedPermissions.remove(eachPerm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008166 }
8167 }
8168 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008169 int newGids[] = globalGids;
8170 for (String eachPerm : sus.grantedPermissions) {
8171 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07008172 if (bp != null) {
8173 newGids = appendInts(newGids, bp.gids);
8174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008175 }
8176 sus.gids = newGids;
8177 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07008178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 private int removePackageLP(String name) {
8180 PackageSetting p = mPackages.get(name);
8181 if (p != null) {
8182 mPackages.remove(name);
8183 if (p.sharedUser != null) {
8184 p.sharedUser.packages.remove(p);
8185 if (p.sharedUser.packages.size() == 0) {
8186 mSharedUsers.remove(p.sharedUser.name);
8187 removeUserIdLP(p.sharedUser.userId);
8188 return p.sharedUser.userId;
8189 }
8190 } else {
8191 removeUserIdLP(p.userId);
8192 return p.userId;
8193 }
8194 }
8195 return -1;
8196 }
8197
8198 private boolean addUserIdLP(int uid, Object obj, Object name) {
8199 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
8200 return false;
8201 }
8202
8203 if (uid >= FIRST_APPLICATION_UID) {
8204 int N = mUserIds.size();
8205 final int index = uid - FIRST_APPLICATION_UID;
8206 while (index >= N) {
8207 mUserIds.add(null);
8208 N++;
8209 }
8210 if (mUserIds.get(index) != null) {
8211 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07008212 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008213 + " name=" + name);
8214 return false;
8215 }
8216 mUserIds.set(index, obj);
8217 } else {
8218 if (mOtherUserIds.get(uid) != null) {
8219 reportSettingsProblem(Log.ERROR,
8220 "Adding duplicate shared id: " + uid
8221 + " name=" + name);
8222 return false;
8223 }
8224 mOtherUserIds.put(uid, obj);
8225 }
8226 return true;
8227 }
8228
8229 public Object getUserIdLP(int uid) {
8230 if (uid >= FIRST_APPLICATION_UID) {
8231 int N = mUserIds.size();
8232 final int index = uid - FIRST_APPLICATION_UID;
8233 return index < N ? mUserIds.get(index) : null;
8234 } else {
8235 return mOtherUserIds.get(uid);
8236 }
8237 }
8238
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008239 private Set<String> findPackagesWithFlag(int flag) {
8240 Set<String> ret = new HashSet<String>();
8241 for (PackageSetting ps : mPackages.values()) {
8242 // Has to match atleast all the flag bits set on flag
8243 if ((ps.pkgFlags & flag) == flag) {
8244 ret.add(ps.name);
8245 }
8246 }
8247 return ret;
8248 }
8249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008250 private void removeUserIdLP(int uid) {
8251 if (uid >= FIRST_APPLICATION_UID) {
8252 int N = mUserIds.size();
8253 final int index = uid - FIRST_APPLICATION_UID;
8254 if (index < N) mUserIds.set(index, null);
8255 } else {
8256 mOtherUserIds.remove(uid);
8257 }
8258 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 void writeLP() {
8261 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
8262
8263 // Keep the old settings around until we know the new ones have
8264 // been successfully written.
8265 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008266 // Presence of backup settings file indicates that we failed
8267 // to persist settings earlier. So preserve the older
8268 // backup for future reference since the current settings
8269 // might have been corrupted.
8270 if (!mBackupSettingsFilename.exists()) {
8271 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008272 Slog.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008273 return;
8274 }
8275 } else {
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07008276 mSettingsFilename.delete();
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008277 Slog.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07008278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008279 }
8280
8281 mPastSignatures.clear();
8282
8283 try {
8284 FileOutputStream str = new FileOutputStream(mSettingsFilename);
8285
8286 //XmlSerializer serializer = XmlUtils.serializerInstance();
8287 XmlSerializer serializer = new FastXmlSerializer();
8288 serializer.setOutput(str, "utf-8");
8289 serializer.startDocument(null, true);
8290 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
8291
8292 serializer.startTag(null, "packages");
8293
8294 serializer.startTag(null, "permission-trees");
8295 for (BasePermission bp : mPermissionTrees.values()) {
8296 writePermission(serializer, bp);
8297 }
8298 serializer.endTag(null, "permission-trees");
8299
8300 serializer.startTag(null, "permissions");
8301 for (BasePermission bp : mPermissions.values()) {
8302 writePermission(serializer, bp);
8303 }
8304 serializer.endTag(null, "permissions");
8305
8306 for (PackageSetting pkg : mPackages.values()) {
8307 writePackage(serializer, pkg);
8308 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008310 for (PackageSetting pkg : mDisabledSysPackages.values()) {
8311 writeDisabledSysPackage(serializer, pkg);
8312 }
8313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008314 serializer.startTag(null, "preferred-activities");
8315 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
8316 serializer.startTag(null, "item");
8317 pa.writeToXml(serializer);
8318 serializer.endTag(null, "item");
8319 }
8320 serializer.endTag(null, "preferred-activities");
8321
8322 for (SharedUserSetting usr : mSharedUsers.values()) {
8323 serializer.startTag(null, "shared-user");
8324 serializer.attribute(null, "name", usr.name);
8325 serializer.attribute(null, "userId",
8326 Integer.toString(usr.userId));
8327 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
8328 serializer.startTag(null, "perms");
8329 for (String name : usr.grantedPermissions) {
8330 serializer.startTag(null, "item");
8331 serializer.attribute(null, "name", name);
8332 serializer.endTag(null, "item");
8333 }
8334 serializer.endTag(null, "perms");
8335 serializer.endTag(null, "shared-user");
8336 }
8337
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008338 if (mPackagesToBeCleaned.size() > 0) {
8339 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
8340 serializer.startTag(null, "cleaning-package");
8341 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
8342 serializer.endTag(null, "cleaning-package");
8343 }
8344 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008345
8346 if (mRenamedPackages.size() > 0) {
8347 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
8348 serializer.startTag(null, "renamed-package");
8349 serializer.attribute(null, "new", e.getKey());
8350 serializer.attribute(null, "old", e.getValue());
8351 serializer.endTag(null, "renamed-package");
8352 }
8353 }
8354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008355 serializer.endTag(null, "packages");
8356
8357 serializer.endDocument();
8358
8359 str.flush();
8360 str.close();
8361
8362 // New settings successfully written, old ones are no longer
8363 // needed.
8364 mBackupSettingsFilename.delete();
8365 FileUtils.setPermissions(mSettingsFilename.toString(),
8366 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8367 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8368 |FileUtils.S_IROTH,
8369 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008370
8371 // Write package list file now, use a JournaledFile.
8372 //
8373 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
8374 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
8375
8376 str = new FileOutputStream(journal.chooseForWrite());
8377 try {
8378 StringBuilder sb = new StringBuilder();
8379 for (PackageSetting pkg : mPackages.values()) {
8380 ApplicationInfo ai = pkg.pkg.applicationInfo;
8381 String dataPath = ai.dataDir;
8382 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
8383
8384 // Avoid any application that has a space in its path
8385 // or that is handled by the system.
8386 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
8387 continue;
8388
8389 // we store on each line the following information for now:
8390 //
8391 // pkgName - package name
8392 // userId - application-specific user id
8393 // debugFlag - 0 or 1 if the package is debuggable.
8394 // dataPath - path to package's data path
8395 //
8396 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
8397 //
8398 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
8399 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
8400 // system/core/run-as/run-as.c
8401 //
8402 sb.setLength(0);
8403 sb.append(ai.packageName);
8404 sb.append(" ");
8405 sb.append((int)ai.uid);
8406 sb.append(isDebug ? " 1 " : " 0 ");
8407 sb.append(dataPath);
8408 sb.append("\n");
8409 str.write(sb.toString().getBytes());
8410 }
8411 str.flush();
8412 str.close();
8413 journal.commit();
8414 }
8415 catch (Exception e) {
8416 journal.rollback();
8417 }
8418
8419 FileUtils.setPermissions(mPackageListFilename.toString(),
8420 FileUtils.S_IRUSR|FileUtils.S_IWUSR
8421 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
8422 |FileUtils.S_IROTH,
8423 -1, -1);
8424
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008425 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426
8427 } catch(XmlPullParserException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008428 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008429 } catch(java.io.IOException e) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008430 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008431 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08008432 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07008433 if (mSettingsFilename.exists()) {
8434 if (!mSettingsFilename.delete()) {
8435 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
8436 }
8437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008438 //Debug.stopMethodTracing();
8439 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008440
8441 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008442 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008443 serializer.startTag(null, "updated-package");
8444 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008445 if (pkg.realName != null) {
8446 serializer.attribute(null, "realName", pkg.realName);
8447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 serializer.attribute(null, "codePath", pkg.codePathString);
8449 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008450 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008451 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8452 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8453 }
8454 if (pkg.sharedUser == null) {
8455 serializer.attribute(null, "userId",
8456 Integer.toString(pkg.userId));
8457 } else {
8458 serializer.attribute(null, "sharedUserId",
8459 Integer.toString(pkg.userId));
8460 }
8461 serializer.startTag(null, "perms");
8462 if (pkg.sharedUser == null) {
8463 // If this is a shared user, the permissions will
8464 // be written there. We still need to write an
8465 // empty permissions list so permissionsFixed will
8466 // be set.
8467 for (final String name : pkg.grantedPermissions) {
8468 BasePermission bp = mPermissions.get(name);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008469 if (bp != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008470 // We only need to write signature or system permissions but this wont
8471 // match the semantics of grantedPermissions. So write all permissions.
8472 serializer.startTag(null, "item");
8473 serializer.attribute(null, "name", name);
8474 serializer.endTag(null, "item");
8475 }
8476 }
8477 }
8478 serializer.endTag(null, "perms");
8479 serializer.endTag(null, "updated-package");
8480 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008481
8482 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008483 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008484 serializer.startTag(null, "package");
8485 serializer.attribute(null, "name", pkg.name);
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008486 if (pkg.realName != null) {
8487 serializer.attribute(null, "realName", pkg.realName);
8488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008489 serializer.attribute(null, "codePath", pkg.codePathString);
8490 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
8491 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
8492 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008493 serializer.attribute(null, "flags",
8494 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008495 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008496 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008497 if (pkg.sharedUser == null) {
8498 serializer.attribute(null, "userId",
8499 Integer.toString(pkg.userId));
8500 } else {
8501 serializer.attribute(null, "sharedUserId",
8502 Integer.toString(pkg.userId));
8503 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008504 if (pkg.uidError) {
8505 serializer.attribute(null, "uidError", "true");
8506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008507 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
8508 serializer.attribute(null, "enabled",
8509 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
8510 ? "true" : "false");
8511 }
8512 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
8513 serializer.attribute(null, "installStatus", "false");
8514 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008515 if (pkg.installerPackageName != null) {
8516 serializer.attribute(null, "installer", pkg.installerPackageName);
8517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
8519 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
8520 serializer.startTag(null, "perms");
8521 if (pkg.sharedUser == null) {
8522 // If this is a shared user, the permissions will
8523 // be written there. We still need to write an
8524 // empty permissions list so permissionsFixed will
8525 // be set.
8526 for (final String name : pkg.grantedPermissions) {
8527 serializer.startTag(null, "item");
8528 serializer.attribute(null, "name", name);
8529 serializer.endTag(null, "item");
8530 }
8531 }
8532 serializer.endTag(null, "perms");
8533 }
8534 if (pkg.disabledComponents.size() > 0) {
8535 serializer.startTag(null, "disabled-components");
8536 for (final String name : pkg.disabledComponents) {
8537 serializer.startTag(null, "item");
8538 serializer.attribute(null, "name", name);
8539 serializer.endTag(null, "item");
8540 }
8541 serializer.endTag(null, "disabled-components");
8542 }
8543 if (pkg.enabledComponents.size() > 0) {
8544 serializer.startTag(null, "enabled-components");
8545 for (final String name : pkg.enabledComponents) {
8546 serializer.startTag(null, "item");
8547 serializer.attribute(null, "name", name);
8548 serializer.endTag(null, "item");
8549 }
8550 serializer.endTag(null, "enabled-components");
8551 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553 serializer.endTag(null, "package");
8554 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008556 void writePermission(XmlSerializer serializer, BasePermission bp)
8557 throws XmlPullParserException, java.io.IOException {
8558 if (bp.type != BasePermission.TYPE_BUILTIN
8559 && bp.sourcePackage != null) {
8560 serializer.startTag(null, "item");
8561 serializer.attribute(null, "name", bp.name);
8562 serializer.attribute(null, "package", bp.sourcePackage);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008563 if (bp.protectionLevel !=
8564 PermissionInfo.PROTECTION_NORMAL) {
8565 serializer.attribute(null, "protection",
8566 Integer.toString(bp.protectionLevel));
8567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 if (DEBUG_SETTINGS) Log.v(TAG,
8569 "Writing perm: name=" + bp.name + " type=" + bp.type);
8570 if (bp.type == BasePermission.TYPE_DYNAMIC) {
8571 PermissionInfo pi = bp.perm != null ? bp.perm.info
8572 : bp.pendingInfo;
8573 if (pi != null) {
8574 serializer.attribute(null, "type", "dynamic");
8575 if (pi.icon != 0) {
8576 serializer.attribute(null, "icon",
8577 Integer.toString(pi.icon));
8578 }
8579 if (pi.nonLocalizedLabel != null) {
8580 serializer.attribute(null, "label",
8581 pi.nonLocalizedLabel.toString());
8582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008583 }
8584 }
8585 serializer.endTag(null, "item");
8586 }
8587 }
8588
8589 String getReadMessagesLP() {
8590 return mReadMessages.toString();
8591 }
8592
Oscar Montemayora8529f62009-11-18 10:14:20 -08008593 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
8595 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08008596 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008597 while(its.hasNext()) {
8598 String key = its.next();
8599 PackageSetting ps = mPackages.get(key);
8600 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08008601 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008602 }
8603 }
8604 return ret;
8605 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 boolean readLP() {
8608 FileInputStream str = null;
8609 if (mBackupSettingsFilename.exists()) {
8610 try {
8611 str = new FileInputStream(mBackupSettingsFilename);
8612 mReadMessages.append("Reading from backup settings file\n");
8613 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008614 if (mSettingsFilename.exists()) {
8615 // If both the backup and settings file exist, we
8616 // ignore the settings since it might have been
8617 // corrupted.
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008618 Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename);
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07008619 mSettingsFilename.delete();
8620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008621 } catch (java.io.IOException e) {
8622 // We'll try for the normal settings file.
8623 }
8624 }
8625
8626 mPastSignatures.clear();
8627
8628 try {
8629 if (str == null) {
8630 if (!mSettingsFilename.exists()) {
8631 mReadMessages.append("No settings file found\n");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008632 Slog.i(TAG, "No current settings file!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008633 return false;
8634 }
8635 str = new FileInputStream(mSettingsFilename);
8636 }
8637 XmlPullParser parser = Xml.newPullParser();
8638 parser.setInput(str, null);
8639
8640 int type;
8641 while ((type=parser.next()) != XmlPullParser.START_TAG
8642 && type != XmlPullParser.END_DOCUMENT) {
8643 ;
8644 }
8645
8646 if (type != XmlPullParser.START_TAG) {
8647 mReadMessages.append("No start tag found in settings file\n");
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008648 Slog.e(TAG, "No start tag found in package manager settings");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 return false;
8650 }
8651
8652 int outerDepth = parser.getDepth();
8653 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8654 && (type != XmlPullParser.END_TAG
8655 || parser.getDepth() > outerDepth)) {
8656 if (type == XmlPullParser.END_TAG
8657 || type == XmlPullParser.TEXT) {
8658 continue;
8659 }
8660
8661 String tagName = parser.getName();
8662 if (tagName.equals("package")) {
8663 readPackageLP(parser);
8664 } else if (tagName.equals("permissions")) {
8665 readPermissionsLP(mPermissions, parser);
8666 } else if (tagName.equals("permission-trees")) {
8667 readPermissionsLP(mPermissionTrees, parser);
8668 } else if (tagName.equals("shared-user")) {
8669 readSharedUserLP(parser);
8670 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08008671 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 } else if (tagName.equals("preferred-activities")) {
8673 readPreferredActivitiesLP(parser);
8674 } else if(tagName.equals("updated-package")) {
8675 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008676 } else if (tagName.equals("cleaning-package")) {
8677 String name = parser.getAttributeValue(null, "name");
8678 if (name != null) {
8679 mPackagesToBeCleaned.add(name);
8680 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008681 } else if (tagName.equals("renamed-package")) {
8682 String nname = parser.getAttributeValue(null, "new");
8683 String oname = parser.getAttributeValue(null, "old");
8684 if (nname != null && oname != null) {
8685 mRenamedPackages.put(nname, oname);
8686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008687 } else {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008688 Slog.w(TAG, "Unknown element under <packages>: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008689 + parser.getName());
8690 XmlUtils.skipCurrentTag(parser);
8691 }
8692 }
8693
8694 str.close();
8695
8696 } catch(XmlPullParserException e) {
8697 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008698 Slog.e(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008699
8700 } catch(java.io.IOException e) {
8701 mReadMessages.append("Error reading: " + e.toString());
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008702 Slog.e(TAG, "Error reading package manager settings", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008703
8704 }
8705
8706 int N = mPendingPackages.size();
8707 for (int i=0; i<N; i++) {
8708 final PendingPackage pp = mPendingPackages.get(i);
8709 Object idObj = getUserIdLP(pp.sharedId);
8710 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008711 PackageSetting p = getPackageLP(pp.name, null, pp.realName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008712 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008713 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008714 if (p == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008715 Slog.w(TAG, "Unable to create application package for "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008716 + pp.name);
8717 continue;
8718 }
8719 p.copyFrom(pp);
8720 } else if (idObj != null) {
8721 String msg = "Bad package setting: package " + pp.name
8722 + " has shared uid " + pp.sharedId
8723 + " that is not a shared uid\n";
8724 mReadMessages.append(msg);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008725 Slog.e(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 } else {
8727 String msg = "Bad package setting: package " + pp.name
8728 + " has shared uid " + pp.sharedId
8729 + " that is not defined\n";
8730 mReadMessages.append(msg);
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08008731 Slog.e(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 }
8733 }
8734 mPendingPackages.clear();
8735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 mReadMessages.append("Read completed successfully: "
8737 + mPackages.size() + " packages, "
8738 + mSharedUsers.size() + " shared uids\n");
8739
8740 return true;
8741 }
8742
8743 private int readInt(XmlPullParser parser, String ns, String name,
8744 int defValue) {
8745 String v = parser.getAttributeValue(ns, name);
8746 try {
8747 if (v == null) {
8748 return defValue;
8749 }
8750 return Integer.parseInt(v);
8751 } catch (NumberFormatException e) {
8752 reportSettingsProblem(Log.WARN,
8753 "Error in package manager settings: attribute " +
8754 name + " has bad integer value " + v + " at "
8755 + parser.getPositionDescription());
8756 }
8757 return defValue;
8758 }
8759
8760 private void readPermissionsLP(HashMap<String, BasePermission> out,
8761 XmlPullParser parser)
8762 throws IOException, XmlPullParserException {
8763 int outerDepth = parser.getDepth();
8764 int type;
8765 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8766 && (type != XmlPullParser.END_TAG
8767 || parser.getDepth() > outerDepth)) {
8768 if (type == XmlPullParser.END_TAG
8769 || type == XmlPullParser.TEXT) {
8770 continue;
8771 }
8772
8773 String tagName = parser.getName();
8774 if (tagName.equals("item")) {
8775 String name = parser.getAttributeValue(null, "name");
8776 String sourcePackage = parser.getAttributeValue(null, "package");
8777 String ptype = parser.getAttributeValue(null, "type");
8778 if (name != null && sourcePackage != null) {
8779 boolean dynamic = "dynamic".equals(ptype);
8780 BasePermission bp = new BasePermission(name, sourcePackage,
8781 dynamic
8782 ? BasePermission.TYPE_DYNAMIC
8783 : BasePermission.TYPE_NORMAL);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008784 bp.protectionLevel = readInt(parser, null, "protection",
8785 PermissionInfo.PROTECTION_NORMAL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008786 if (dynamic) {
8787 PermissionInfo pi = new PermissionInfo();
8788 pi.packageName = sourcePackage.intern();
8789 pi.name = name.intern();
8790 pi.icon = readInt(parser, null, "icon", 0);
8791 pi.nonLocalizedLabel = parser.getAttributeValue(
8792 null, "label");
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07008793 pi.protectionLevel = bp.protectionLevel;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 bp.pendingInfo = pi;
8795 }
8796 out.put(bp.name, bp);
8797 } else {
8798 reportSettingsProblem(Log.WARN,
8799 "Error in package manager settings: permissions has"
8800 + " no name at " + parser.getPositionDescription());
8801 }
8802 } else {
8803 reportSettingsProblem(Log.WARN,
8804 "Unknown element reading permissions: "
8805 + parser.getName() + " at "
8806 + parser.getPositionDescription());
8807 }
8808 XmlUtils.skipCurrentTag(parser);
8809 }
8810 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008812 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008813 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008814 String name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008815 String realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008816 String codePathStr = parser.getAttributeValue(null, "codePath");
8817 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008818 if (resourcePathStr == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 resourcePathStr = codePathStr;
8820 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008821 String version = parser.getAttributeValue(null, "version");
8822 int versionCode = 0;
8823 if (version != null) {
8824 try {
8825 versionCode = Integer.parseInt(version);
8826 } catch (NumberFormatException e) {
8827 }
8828 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008830 int pkgFlags = 0;
8831 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008832 PackageSetting ps = new PackageSetting(name, realName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008833 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008834 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 String timeStampStr = parser.getAttributeValue(null, "ts");
8836 if (timeStampStr != null) {
8837 try {
8838 long timeStamp = Long.parseLong(timeStampStr);
8839 ps.setTimeStamp(timeStamp, timeStampStr);
8840 } catch (NumberFormatException e) {
8841 }
8842 }
8843 String idStr = parser.getAttributeValue(null, "userId");
8844 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
8845 if(ps.userId <= 0) {
8846 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8847 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
8848 }
8849 int outerDepth = parser.getDepth();
8850 int type;
8851 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8852 && (type != XmlPullParser.END_TAG
8853 || parser.getDepth() > outerDepth)) {
8854 if (type == XmlPullParser.END_TAG
8855 || type == XmlPullParser.TEXT) {
8856 continue;
8857 }
8858
8859 String tagName = parser.getName();
8860 if (tagName.equals("perms")) {
8861 readGrantedPermissionsLP(parser,
8862 ps.grantedPermissions);
8863 } else {
8864 reportSettingsProblem(Log.WARN,
8865 "Unknown element under <updated-package>: "
8866 + parser.getName());
8867 XmlUtils.skipCurrentTag(parser);
8868 }
8869 }
8870 mDisabledSysPackages.put(name, ps);
8871 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008873 private void readPackageLP(XmlPullParser parser)
8874 throws XmlPullParserException, IOException {
8875 String name = null;
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008876 String realName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 String idStr = null;
8878 String sharedIdStr = null;
8879 String codePathStr = null;
8880 String resourcePathStr = null;
8881 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02008882 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008883 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008884 int pkgFlags = 0;
8885 String timeStampStr;
8886 long timeStamp = 0;
8887 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008888 String version = null;
8889 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008890 try {
8891 name = parser.getAttributeValue(null, "name");
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008892 realName = parser.getAttributeValue(null, "realName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008893 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008894 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008895 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
8896 codePathStr = parser.getAttributeValue(null, "codePath");
8897 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008898 version = parser.getAttributeValue(null, "version");
8899 if (version != null) {
8900 try {
8901 versionCode = Integer.parseInt(version);
8902 } catch (NumberFormatException e) {
8903 }
8904 }
Jacek Surazski65e13172009-04-28 15:26:38 +02008905 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008906
8907 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008908 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008909 try {
8910 pkgFlags = Integer.parseInt(systemStr);
8911 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008912 }
8913 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008914 // For backward compatibility
8915 systemStr = parser.getAttributeValue(null, "system");
8916 if (systemStr != null) {
8917 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
8918 } else {
8919 // Old settings that don't specify system... just treat
8920 // them as system, good enough.
8921 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008923 }
8924 timeStampStr = parser.getAttributeValue(null, "ts");
8925 if (timeStampStr != null) {
8926 try {
8927 timeStamp = Long.parseLong(timeStampStr);
8928 } catch (NumberFormatException e) {
8929 }
8930 }
8931 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
8932 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
8933 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8934 if (resourcePathStr == null) {
8935 resourcePathStr = codePathStr;
8936 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008937 if (realName != null) {
8938 realName = realName.intern();
8939 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008940 if (name == null) {
8941 reportSettingsProblem(Log.WARN,
8942 "Error in package manager settings: <package> has no name at "
8943 + parser.getPositionDescription());
8944 } else if (codePathStr == null) {
8945 reportSettingsProblem(Log.WARN,
8946 "Error in package manager settings: <package> has no codePath at "
8947 + parser.getPositionDescription());
8948 } else if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008949 packageSetting = addPackageLP(name.intern(), realName,
8950 new File(codePathStr), new File(resourcePathStr),
8951 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008952 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8953 + ": userId=" + userId + " pkg=" + packageSetting);
8954 if (packageSetting == null) {
8955 reportSettingsProblem(Log.ERROR,
8956 "Failure adding uid " + userId
8957 + " while parsing settings at "
8958 + parser.getPositionDescription());
8959 } else {
8960 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8961 }
8962 } else if (sharedIdStr != null) {
8963 userId = sharedIdStr != null
8964 ? Integer.parseInt(sharedIdStr) : 0;
8965 if (userId > 0) {
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08008966 packageSetting = new PendingPackage(name.intern(), realName,
8967 new File(codePathStr), new File(resourcePathStr),
8968 userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008969 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8970 mPendingPackages.add((PendingPackage) packageSetting);
8971 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8972 + ": sharedUserId=" + userId + " pkg="
8973 + packageSetting);
8974 } else {
8975 reportSettingsProblem(Log.WARN,
8976 "Error in package manager settings: package "
8977 + name + " has bad sharedId " + sharedIdStr
8978 + " at " + parser.getPositionDescription());
8979 }
8980 } else {
8981 reportSettingsProblem(Log.WARN,
8982 "Error in package manager settings: package "
8983 + name + " has bad userId " + idStr + " at "
8984 + parser.getPositionDescription());
8985 }
8986 } catch (NumberFormatException e) {
8987 reportSettingsProblem(Log.WARN,
8988 "Error in package manager settings: package "
8989 + name + " has bad userId " + idStr + " at "
8990 + parser.getPositionDescription());
8991 }
8992 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008993 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02008994 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008995 final String enabledStr = parser.getAttributeValue(null, "enabled");
8996 if (enabledStr != null) {
8997 if (enabledStr.equalsIgnoreCase("true")) {
8998 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
8999 } else if (enabledStr.equalsIgnoreCase("false")) {
9000 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
9001 } else if (enabledStr.equalsIgnoreCase("default")) {
9002 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9003 } else {
9004 reportSettingsProblem(Log.WARN,
9005 "Error in package manager settings: package "
9006 + name + " has bad enabled value: " + idStr
9007 + " at " + parser.getPositionDescription());
9008 }
9009 } else {
9010 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
9011 }
9012 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
9013 if (installStatusStr != null) {
9014 if (installStatusStr.equalsIgnoreCase("false")) {
9015 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
9016 } else {
9017 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
9018 }
9019 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009021 int outerDepth = parser.getDepth();
9022 int type;
9023 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9024 && (type != XmlPullParser.END_TAG
9025 || parser.getDepth() > outerDepth)) {
9026 if (type == XmlPullParser.END_TAG
9027 || type == XmlPullParser.TEXT) {
9028 continue;
9029 }
9030
9031 String tagName = parser.getName();
9032 if (tagName.equals("disabled-components")) {
9033 readDisabledComponentsLP(packageSetting, parser);
9034 } else if (tagName.equals("enabled-components")) {
9035 readEnabledComponentsLP(packageSetting, parser);
9036 } else if (tagName.equals("sigs")) {
9037 packageSetting.signatures.readXml(parser, mPastSignatures);
9038 } else if (tagName.equals("perms")) {
9039 readGrantedPermissionsLP(parser,
Dianne Hackbornf657b632010-03-22 18:08:07 -07009040 packageSetting.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009041 packageSetting.permissionsFixed = true;
9042 } else {
9043 reportSettingsProblem(Log.WARN,
9044 "Unknown element under <package>: "
9045 + parser.getName());
9046 XmlUtils.skipCurrentTag(parser);
9047 }
9048 }
9049 } else {
9050 XmlUtils.skipCurrentTag(parser);
9051 }
9052 }
9053
9054 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
9055 XmlPullParser parser)
9056 throws IOException, XmlPullParserException {
9057 int outerDepth = parser.getDepth();
9058 int type;
9059 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9060 && (type != XmlPullParser.END_TAG
9061 || parser.getDepth() > outerDepth)) {
9062 if (type == XmlPullParser.END_TAG
9063 || type == XmlPullParser.TEXT) {
9064 continue;
9065 }
9066
9067 String tagName = parser.getName();
9068 if (tagName.equals("item")) {
9069 String name = parser.getAttributeValue(null, "name");
9070 if (name != null) {
9071 packageSetting.disabledComponents.add(name.intern());
9072 } else {
9073 reportSettingsProblem(Log.WARN,
9074 "Error in package manager settings: <disabled-components> has"
9075 + " no name at " + parser.getPositionDescription());
9076 }
9077 } else {
9078 reportSettingsProblem(Log.WARN,
9079 "Unknown element under <disabled-components>: "
9080 + parser.getName());
9081 }
9082 XmlUtils.skipCurrentTag(parser);
9083 }
9084 }
9085
9086 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
9087 XmlPullParser parser)
9088 throws IOException, XmlPullParserException {
9089 int outerDepth = parser.getDepth();
9090 int type;
9091 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9092 && (type != XmlPullParser.END_TAG
9093 || parser.getDepth() > outerDepth)) {
9094 if (type == XmlPullParser.END_TAG
9095 || type == XmlPullParser.TEXT) {
9096 continue;
9097 }
9098
9099 String tagName = parser.getName();
9100 if (tagName.equals("item")) {
9101 String name = parser.getAttributeValue(null, "name");
9102 if (name != null) {
9103 packageSetting.enabledComponents.add(name.intern());
9104 } else {
9105 reportSettingsProblem(Log.WARN,
9106 "Error in package manager settings: <enabled-components> has"
9107 + " no name at " + parser.getPositionDescription());
9108 }
9109 } else {
9110 reportSettingsProblem(Log.WARN,
9111 "Unknown element under <enabled-components>: "
9112 + parser.getName());
9113 }
9114 XmlUtils.skipCurrentTag(parser);
9115 }
9116 }
9117
9118 private void readSharedUserLP(XmlPullParser parser)
9119 throws XmlPullParserException, IOException {
9120 String name = null;
9121 String idStr = null;
9122 int pkgFlags = 0;
9123 SharedUserSetting su = null;
9124 try {
9125 name = parser.getAttributeValue(null, "name");
9126 idStr = parser.getAttributeValue(null, "userId");
9127 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
9128 if ("true".equals(parser.getAttributeValue(null, "system"))) {
9129 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
9130 }
9131 if (name == null) {
9132 reportSettingsProblem(Log.WARN,
9133 "Error in package manager settings: <shared-user> has no name at "
9134 + parser.getPositionDescription());
9135 } else if (userId == 0) {
9136 reportSettingsProblem(Log.WARN,
9137 "Error in package manager settings: shared-user "
9138 + name + " has bad userId " + idStr + " at "
9139 + parser.getPositionDescription());
9140 } else {
9141 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
9142 reportSettingsProblem(Log.ERROR,
9143 "Occurred while parsing settings at "
9144 + parser.getPositionDescription());
9145 }
9146 }
9147 } catch (NumberFormatException e) {
9148 reportSettingsProblem(Log.WARN,
9149 "Error in package manager settings: package "
9150 + name + " has bad userId " + idStr + " at "
9151 + parser.getPositionDescription());
9152 };
9153
9154 if (su != null) {
9155 int outerDepth = parser.getDepth();
9156 int type;
9157 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9158 && (type != XmlPullParser.END_TAG
9159 || parser.getDepth() > outerDepth)) {
9160 if (type == XmlPullParser.END_TAG
9161 || type == XmlPullParser.TEXT) {
9162 continue;
9163 }
9164
9165 String tagName = parser.getName();
9166 if (tagName.equals("sigs")) {
9167 su.signatures.readXml(parser, mPastSignatures);
9168 } else if (tagName.equals("perms")) {
Dianne Hackbornf657b632010-03-22 18:08:07 -07009169 readGrantedPermissionsLP(parser, su.grantedPermissions);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009170 } else {
9171 reportSettingsProblem(Log.WARN,
9172 "Unknown element under <shared-user>: "
9173 + parser.getName());
9174 XmlUtils.skipCurrentTag(parser);
9175 }
9176 }
9177
9178 } else {
9179 XmlUtils.skipCurrentTag(parser);
9180 }
9181 }
9182
9183 private void readGrantedPermissionsLP(XmlPullParser parser,
9184 HashSet<String> outPerms) throws IOException, XmlPullParserException {
9185 int outerDepth = parser.getDepth();
9186 int type;
9187 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9188 && (type != XmlPullParser.END_TAG
9189 || parser.getDepth() > outerDepth)) {
9190 if (type == XmlPullParser.END_TAG
9191 || type == XmlPullParser.TEXT) {
9192 continue;
9193 }
9194
9195 String tagName = parser.getName();
9196 if (tagName.equals("item")) {
9197 String name = parser.getAttributeValue(null, "name");
9198 if (name != null) {
9199 outPerms.add(name.intern());
9200 } else {
9201 reportSettingsProblem(Log.WARN,
9202 "Error in package manager settings: <perms> has"
9203 + " no name at " + parser.getPositionDescription());
9204 }
9205 } else {
9206 reportSettingsProblem(Log.WARN,
9207 "Unknown element under <perms>: "
9208 + parser.getName());
9209 }
9210 XmlUtils.skipCurrentTag(parser);
9211 }
9212 }
9213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009214 private void readPreferredActivitiesLP(XmlPullParser parser)
9215 throws XmlPullParserException, IOException {
9216 int outerDepth = parser.getDepth();
9217 int type;
9218 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
9219 && (type != XmlPullParser.END_TAG
9220 || parser.getDepth() > outerDepth)) {
9221 if (type == XmlPullParser.END_TAG
9222 || type == XmlPullParser.TEXT) {
9223 continue;
9224 }
9225
9226 String tagName = parser.getName();
9227 if (tagName.equals("item")) {
9228 PreferredActivity pa = new PreferredActivity(parser);
9229 if (pa.mParseError == null) {
9230 mPreferredActivities.addFilter(pa);
9231 } else {
9232 reportSettingsProblem(Log.WARN,
9233 "Error in package manager settings: <preferred-activity> "
9234 + pa.mParseError + " at "
9235 + parser.getPositionDescription());
9236 }
9237 } else {
9238 reportSettingsProblem(Log.WARN,
9239 "Unknown element under <preferred-activities>: "
9240 + parser.getName());
9241 XmlUtils.skipCurrentTag(parser);
9242 }
9243 }
9244 }
9245
9246 // Returns -1 if we could not find an available UserId to assign
9247 private int newUserIdLP(Object obj) {
9248 // Let's be stupidly inefficient for now...
9249 final int N = mUserIds.size();
9250 for (int i=0; i<N; i++) {
9251 if (mUserIds.get(i) == null) {
9252 mUserIds.set(i, obj);
9253 return FIRST_APPLICATION_UID + i;
9254 }
9255 }
9256
9257 // None left?
9258 if (N >= MAX_APPLICATION_UIDS) {
9259 return -1;
9260 }
9261
9262 mUserIds.add(obj);
9263 return FIRST_APPLICATION_UID + N;
9264 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 public PackageSetting getDisabledSystemPkg(String name) {
9267 synchronized(mPackages) {
9268 PackageSetting ps = mDisabledSysPackages.get(name);
9269 return ps;
9270 }
9271 }
9272
9273 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
9274 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
9275 if (Config.LOGV) {
9276 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
9277 + " componentName = " + componentInfo.name);
9278 Log.v(TAG, "enabledComponents: "
9279 + Arrays.toString(packageSettings.enabledComponents.toArray()));
9280 Log.v(TAG, "disabledComponents: "
9281 + Arrays.toString(packageSettings.disabledComponents.toArray()));
9282 }
Dianne Hackborn6dee18c2010-02-09 23:59:16 -08009283 if (packageSettings == null) {
9284 if (false) {
9285 Log.w(TAG, "WAITING FOR DEBUGGER");
9286 Debug.waitForDebugger();
9287 Log.i(TAG, "We will crash!");
9288 }
9289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
9291 || ((componentInfo.enabled
9292 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
9293 || (componentInfo.applicationInfo.enabled
9294 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
9295 && !packageSettings.disabledComponents.contains(componentInfo.name))
9296 || packageSettings.enabledComponents.contains(componentInfo.name));
9297 }
9298 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009299
9300 // ------- apps on sdcard specific code -------
9301 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08009302 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08009303 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009304 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009305 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009306
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009307 private String getEncryptKey() {
9308 try {
9309 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
9310 if (sdEncKey == null) {
9311 sdEncKey = SystemKeyStore.getInstance().
9312 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
9313 if (sdEncKey == null) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009314 Slog.e(TAG, "Failed to create encryption keys");
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009315 return null;
9316 }
9317 }
9318 return sdEncKey;
9319 } catch (NoSuchAlgorithmException nsae) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009320 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009321 return null;
9322 }
9323 }
9324
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009325 static String getTempContainerId() {
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009326 String prefix = "smdl2tmp";
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009327 int tmpIdx = 1;
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08009328 String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009329 if (list != null) {
9330 int idx = 0;
9331 int idList[] = new int[MAX_CONTAINERS];
9332 boolean neverFound = true;
9333 for (String name : list) {
9334 // Ignore null entries
9335 if (name == null) {
9336 continue;
9337 }
9338 int sidx = name.indexOf(prefix);
9339 if (sidx == -1) {
9340 // Not a temp file. just ignore
9341 continue;
9342 }
9343 String subStr = name.substring(sidx + prefix.length());
9344 idList[idx] = -1;
9345 if (subStr != null) {
9346 try {
9347 int cid = Integer.parseInt(subStr);
9348 idList[idx++] = cid;
9349 neverFound = false;
9350 } catch (NumberFormatException e) {
9351 }
9352 }
9353 }
9354 if (!neverFound) {
9355 // Sort idList
9356 Arrays.sort(idList);
9357 for (int j = 1; j <= idList.length; j++) {
9358 if (idList[j-1] != j) {
9359 tmpIdx = j;
9360 break;
9361 }
9362 }
9363 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009364 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08009365 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009366 }
9367
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009368 /*
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009369 * Update media status on PackageManager.
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009370 */
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009371 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
9372 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
9373 throw new SecurityException("Media status can only be updated by the system");
9374 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009375 synchronized (mPackages) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08009376 Log.i(TAG, "Updating external media status from " +
9377 (mMediaMounted ? "mounted" : "unmounted") + " to " +
9378 (mediaStatus ? "mounted" : "unmounted"));
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009379 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
9380 mediaStatus+", mMediaMounted=" + mMediaMounted);
9381 if (mediaStatus == mMediaMounted) {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009382 if (reportStatus) {
9383 mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
9384 }
9385 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009386 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009387 mMediaMounted = mediaStatus;
Dianne Hackborne83cefce2010-02-04 17:38:14 -08009388 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009389 // Queue up an async operation since the package installation may take a little while.
9390 mHandler.post(new Runnable() {
9391 public void run() {
9392 mHandler.removeCallbacks(this);
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009393 try {
9394 updateExternalMediaStatusInner(mediaStatus);
9395 } finally {
9396 if (reportStatus) {
9397 mHandler.sendEmptyMessage(UPDATED_MEDIA_STATUS);
9398 }
9399 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009400 }
9401 });
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009402 }
9403
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009404 private void updateExternalMediaStatusInner(boolean mediaStatus) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009405 // If we are up here that means there are packages to be
9406 // enabled or disabled.
Suchi Amalapurapu679bba32010-02-16 11:52:44 -08009407 final String list[] = PackageHelper.getSecureContainerList();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009408 if (list == null || list.length == 0) {
Suchi Amalapurapu8a9ab242010-03-11 16:49:16 -08009409 Log.i(TAG, "No secure containers on sdcard");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009410 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009411 }
Suchi Amalapurapucf6eaea2010-02-23 19:37:45 -08009412
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009413 int uidList[] = new int[list.length];
9414 int num = 0;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009415 HashSet<String> removeCids = new HashSet<String>();
9416 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009417 synchronized (mPackages) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009418 for (String cid : list) {
9419 SdInstallArgs args = new SdInstallArgs(cid);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009420 if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid);
9421 boolean failed = true;
9422 try {
9423 String pkgName = args.getPackageName();
9424 if (pkgName == null) {
9425 continue;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009426 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009427 if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
9428 PackageSetting ps = mSettings.mPackages.get(pkgName);
9429 if (ps != null && ps.codePathString != null &&
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08009430 (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009431 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
9432 " corresponds to pkg : " + pkgName +
9433 " at code path: " + ps.codePathString);
9434 // We do have a valid package installed on sdcard
9435 processCids.put(args, ps.codePathString);
9436 failed = false;
9437 int uid = ps.userId;
9438 if (uid != -1) {
9439 uidList[num++] = uid;
9440 }
9441 }
9442 } finally {
9443 if (failed) {
9444 // Stale container on sdcard. Just delete
9445 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale");
9446 removeCids.add(cid);
9447 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08009448 }
9449 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009450 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009451 // Organize uids
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009452 int uidArr[] = null;
9453 if (num > 0) {
9454 // Sort uid list
9455 Arrays.sort(uidList, 0, num);
9456 // Throw away duplicates
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009457 uidArr = new int[num];
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009458 uidArr[0] = uidList[0];
9459 int di = 0;
9460 for (int i = 1; i < num; i++) {
9461 if (uidList[i-1] != uidList[i]) {
9462 uidArr[di++] = uidList[i];
9463 }
9464 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009465 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009466 // Process packages with valid entries.
9467 if (mediaStatus) {
9468 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009469 loadMediaPackages(processCids, uidArr, removeCids);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009470 startCleaningPackages();
9471 } else {
9472 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009473 unloadMediaPackages(processCids, uidArr);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009474 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009475 }
9476
9477 private void sendResourcesChangedBroadcast(boolean mediaStatus,
9478 ArrayList<String> pkgList, int uidArr[]) {
9479 int size = pkgList.size();
9480 if (size > 0) {
9481 // Send broadcasts here
9482 Bundle extras = new Bundle();
9483 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
9484 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009485 if (uidArr != null) {
9486 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
9487 }
9488 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
9489 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009490 sendPackageBroadcast(action, null, extras);
9491 }
9492 }
9493
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009494 /*
9495 * Look at potentially valid container ids from processCids
9496 * If package information doesn't match the one on record
9497 * or package scanning fails, the cid is added to list of
9498 * removeCids and cleaned up. Since cleaning up containers
9499 * involves destroying them, we do not want any parse
9500 * references to such stale containers. So force gc's
9501 * to avoid unnecessary crashes.
9502 */
9503 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009504 int uidArr[], HashSet<String> removeCids) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009505 ArrayList<String> pkgList = new ArrayList<String>();
9506 Set<SdInstallArgs> keys = processCids.keySet();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009507 boolean doGc = false;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009508 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009509 String codePath = processCids.get(args);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009510 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : "
9511 + args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009512 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009513 try {
9514 // Make sure there are no container errors first.
9515 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED)
9516 != PackageManager.INSTALL_SUCCEEDED) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009517 Slog.e(TAG, "Failed to mount cid : " + args.cid +
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009518 " when installing from sdcard");
9519 continue;
9520 }
9521 // Check code path here.
9522 if (codePath == null || !codePath.equals(args.getCodePath())) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009523 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009524 " does not match one in settings " + codePath);
9525 continue;
9526 }
9527 // Parse package
9528 int parseFlags = PackageParser.PARSE_CHATTY |
Jeff Brown07330792010-03-30 19:57:08 -07009529 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009530 doGc = true;
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009531 synchronized (mInstallLock) {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009532 final PackageParser.Package pkg = scanPackageLI(new File(codePath),
9533 parseFlags, 0);
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009534 // Scan the package
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009535 if (pkg != null) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009536 synchronized (mPackages) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009537 retCode = PackageManager.INSTALL_SUCCEEDED;
9538 pkgList.add(pkg.packageName);
9539 // Post process args
9540 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
9541 }
9542 } else {
Suchi Amalapurapuae181712010-03-30 14:01:02 -07009543 Slog.i(TAG, "Failed to install pkg from " +
9544 codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009545 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009546 }
9547
9548 } finally {
9549 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
9550 // Don't destroy container here. Wait till gc clears things up.
9551 removeCids.add(args.cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009552 }
9553 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009554 }
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009555 synchronized (mPackages) {
Dianne Hackbornaf7cea32010-03-24 12:59:52 -07009556 // Make sure group IDs have been assigned, and any permission
9557 // changes in other apps are accounted for
9558 updatePermissionsLP(null, null, true, false);
Dianne Hackbornd4310ac2010-03-16 22:55:08 -07009559 // Persist settings
9560 mSettings.writeLP();
9561 }
Suchi Amalapurapuc42e29e2010-02-22 16:03:53 -08009562 // Send a broadcast to let everyone know we are done processing
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009563 if (pkgList.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009564 sendResourcesChangedBroadcast(true, pkgList, uidArr);
9565 }
9566 if (doGc) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009567 Runtime.getRuntime().gc();
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009568 }
Suchi Amalapurapuf654a482010-03-23 09:46:22 -07009569 // List stale containers.
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009570 if (removeCids != null) {
9571 for (String cid : removeCids) {
Suchi Amalapurapuf654a482010-03-23 09:46:22 -07009572 Log.w(TAG, "Container " + cid + " is stale");
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009573 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009574 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009575 }
9576
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009577 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids,
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009578 int uidArr[]) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009579 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009580 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009581 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009582 Set<SdInstallArgs> keys = processCids.keySet();
9583 for (SdInstallArgs args : keys) {
9584 String cid = args.cid;
9585 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009586 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009587 // Delete package internally
9588 PackageRemovedInfo outInfo = new PackageRemovedInfo();
9589 synchronized (mInstallLock) {
9590 boolean res = deletePackageLI(pkgName, false,
9591 PackageManager.DONT_DELETE_DATA, outInfo);
9592 if (res) {
9593 pkgList.add(pkgName);
9594 } else {
Jeff Brown07330792010-03-30 19:57:08 -07009595 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009596 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009597 }
9598 }
9599 }
9600 // Send broadcasts
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -07009601 if (pkgList.size() > 0) {
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009602 sendResourcesChangedBroadcast(false, pkgList, uidArr);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08009603 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009604 // Force gc
9605 Runtime.getRuntime().gc();
9606 // Just unmount all valid containers.
9607 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08009608 synchronized (mInstallLock) {
9609 args.doPostDeleteLI(false);
9610 }
9611 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08009612 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009613
9614 public void movePackage(final String packageName,
9615 final IPackageMoveObserver observer, final int flags) {
9616 if (packageName == null) {
9617 return;
9618 }
9619 mContext.enforceCallingOrSelfPermission(
9620 android.Manifest.permission.MOVE_PACKAGE, null);
9621 int returnCode = PackageManager.MOVE_SUCCEEDED;
9622 int currFlags = 0;
9623 int newFlags = 0;
9624 synchronized (mPackages) {
9625 PackageParser.Package pkg = mPackages.get(packageName);
9626 if (pkg == null) {
9627 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
9628 }
9629 // Disable moving fwd locked apps and system packages
9630 if (pkg.applicationInfo != null &&
9631 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009632 Slog.w(TAG, "Cannot move system application");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009633 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
9634 } else if (pkg.applicationInfo != null &&
9635 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009636 Slog.w(TAG, "Cannot move forward locked app.");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009637 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
9638 } else {
9639 // Find install location first
9640 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 &&
9641 (flags & PackageManager.MOVE_INTERNAL) != 0) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009642 Slog.w(TAG, "Ambigous flags specified for move location.");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009643 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9644 } else {
9645 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
9646 PackageManager.INSTALL_EXTERNAL : 0;
Suchi Amalapurapu6069beb2010-03-10 09:46:49 -08009647 currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009648 PackageManager.INSTALL_EXTERNAL : 0;
9649 if (newFlags == currFlags) {
Dianne Hackborna2fd9d12010-03-11 23:40:24 -08009650 Slog.w(TAG, "No move required. Trying to move to same location");
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009651 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
9652 }
9653 }
9654 }
9655 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
9656 processPendingMove(new MoveParams(null, observer, 0, null), returnCode);
9657 } else {
9658 Message msg = mHandler.obtainMessage(INIT_COPY);
9659 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
9660 pkg.applicationInfo.publicSourceDir);
9661 MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
9662 packageName);
9663 msg.obj = mp;
9664 mHandler.sendMessage(msg);
9665 }
9666 }
9667 }
9668
9669 private void processPendingMove(final MoveParams mp, final int currentStatus) {
9670 // Queue up an async operation since the package deletion may take a little while.
9671 mHandler.post(new Runnable() {
9672 public void run() {
9673 mHandler.removeCallbacks(this);
9674 int returnCode = currentStatus;
9675 boolean moveSucceeded = (returnCode == PackageManager.MOVE_SUCCEEDED);
9676 if (moveSucceeded) {
9677 int uid = -1;
9678 synchronized (mPackages) {
9679 uid = mPackages.get(mp.packageName).applicationInfo.uid;
9680 }
9681 ArrayList<String> pkgList = new ArrayList<String>();
9682 pkgList.add(mp.packageName);
9683 int uidArr[] = new int[] { uid };
9684 // Send resources unavailable broadcast
9685 sendResourcesChangedBroadcast(false, pkgList, uidArr);
9686
9687 // Update package code and resource paths
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009688 synchronized (mInstallLock) {
9689 synchronized (mPackages) {
9690 PackageParser.Package pkg = mPackages.get(mp.packageName);
9691 if (pkg != null) {
9692 String oldCodePath = pkg.mPath;
9693 String newCodePath = mp.targetArgs.getCodePath();
9694 String newResPath = mp.targetArgs.getResourcePath();
9695 pkg.mPath = newCodePath;
9696 // Move dex files around
9697 if (moveDexFilesLI(pkg)
9698 != PackageManager.INSTALL_SUCCEEDED) {
9699 // Moving of dex files failed. Set
9700 // error code and abort move.
9701 pkg.mPath = pkg.mScanPath;
9702 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
9703 moveSucceeded = false;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009704 } else {
Suchi Amalapurapuf7f5dda2010-03-23 10:34:28 -07009705 pkg.mScanPath = newCodePath;
9706 pkg.applicationInfo.sourceDir = newCodePath;
9707 pkg.applicationInfo.publicSourceDir = newResPath;
9708 PackageSetting ps = (PackageSetting) pkg.mExtras;
9709 ps.codePath = new File(pkg.applicationInfo.sourceDir);
9710 ps.codePathString = ps.codePath.getPath();
9711 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir);
9712 ps.resourcePathString = ps.resourcePath.getPath();
9713 // Set the application info flag correctly.
9714 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
9715 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9716 } else {
9717 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
9718 }
9719 ps.setFlags(pkg.applicationInfo.flags);
9720 mAppDirs.remove(oldCodePath);
9721 mAppDirs.put(newCodePath, pkg);
9722 // Persist settings
9723 mSettings.writeLP();
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009724 }
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009725 }
9726 }
9727 }
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009728 // Send resources available broadcast
9729 sendResourcesChangedBroadcast(true, pkgList, uidArr);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009730 }
9731 if (!moveSucceeded){
9732 // Clean up failed installation
9733 if (mp.targetArgs != null) {
9734 mp.targetArgs.doPostInstall(
Suchi Amalapurapu9b10ef52010-03-03 09:45:24 -08009735 returnCode);
9736 }
9737 } else {
9738 // Force a gc to clear things up.
9739 Runtime.getRuntime().gc();
9740 // Delete older code
9741 synchronized (mInstallLock) {
9742 mp.srcArgs.doPostDeleteLI(true);
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08009743 }
9744 }
9745 IPackageMoveObserver observer = mp.observer;
9746 if (observer != null) {
9747 try {
9748 observer.packageMoved(mp.packageName, returnCode);
9749 } catch (RemoteException e) {
9750 Log.i(TAG, "Observer no longer exists.");
9751 }
9752 }
9753 }
9754 });
9755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009756}