blob: 1cda2ff5ba1f2eb4ab106d2b662c278acb507731 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080019import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.app.ResolverActivity;
Tom Taylord4a47292009-12-21 13:59:18 -080021import com.android.common.FastXmlSerializer;
22import com.android.common.XmlUtils;
David 'Digit' Turneradd13762010-02-03 17:34:58 -080023import com.android.server.JournaledFile;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27import org.xmlpull.v1.XmlSerializer;
28
29import android.app.ActivityManagerNative;
30import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070035import android.content.IntentSender;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080036import android.content.ServiceConnection;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070037import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.pm.ActivityInfo;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070041import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.IPackageDataObserver;
43import android.content.pm.IPackageDeleteObserver;
44import android.content.pm.IPackageInstallObserver;
45import android.content.pm.IPackageManager;
46import android.content.pm.IPackageStatsObserver;
47import android.content.pm.InstrumentationInfo;
48import android.content.pm.PackageInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.PackageStats;
51import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
52import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
53import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
54import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
55import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
56import android.content.pm.PackageParser;
57import android.content.pm.PermissionInfo;
58import android.content.pm.PermissionGroupInfo;
59import android.content.pm.ProviderInfo;
60import android.content.pm.ResolveInfo;
61import android.content.pm.ServiceInfo;
62import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.net.Uri;
64import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070065import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.os.Bundle;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -080067import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080069import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070070import android.os.Looper;
71import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.os.Parcel;
73import android.os.RemoteException;
74import android.os.Environment;
75import android.os.FileObserver;
76import android.os.FileUtils;
77import android.os.Handler;
San Mehatb1043402010-02-05 08:26:50 -080078import android.os.storage.StorageResultCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.ParcelFileDescriptor;
80import android.os.Process;
81import android.os.ServiceManager;
82import android.os.SystemClock;
83import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080084import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.util.*;
86import android.view.Display;
87import android.view.WindowManager;
88
89import java.io.File;
90import java.io.FileDescriptor;
91import java.io.FileInputStream;
92import java.io.FileNotFoundException;
93import java.io.FileOutputStream;
94import java.io.FileReader;
95import java.io.FilenameFilter;
96import java.io.IOException;
97import java.io.InputStream;
98import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -080099import java.security.NoSuchAlgorithmException;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800100import java.text.SimpleDateFormat;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.util.ArrayList;
102import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700103import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import java.util.Collections;
105import java.util.Comparator;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800106import java.util.Date;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import java.util.Enumeration;
108import java.util.HashMap;
109import java.util.HashSet;
110import java.util.Iterator;
111import java.util.List;
112import java.util.Map;
113import java.util.Set;
114import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800115import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import java.util.zip.ZipFile;
117import java.util.zip.ZipOutputStream;
118
119class PackageManagerService extends IPackageManager.Stub {
120 private static final String TAG = "PackageManager";
121 private static final boolean DEBUG_SETTINGS = false;
122 private static final boolean DEBUG_PREFERRED = false;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800123 private static final boolean DEBUG_UPGRADE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
125 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
126 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400127 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 private static final int FIRST_APPLICATION_UID =
129 Process.FIRST_APPLICATION_UID;
130 private static final int MAX_APPLICATION_UIDS = 1000;
131
132 private static final boolean SHOW_INFO = false;
133
134 private static final boolean GET_CERTIFICATES = true;
135
Oscar Montemayora8529f62009-11-18 10:14:20 -0800136 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 private static final int REMOVE_EVENTS =
139 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
140 private static final int ADD_EVENTS =
141 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
142
143 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
144
145 static final int SCAN_MONITOR = 1<<0;
146 static final int SCAN_NO_DEX = 1<<1;
147 static final int SCAN_FORCE_DEX = 1<<2;
148 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800149 static final int SCAN_NEW_INSTALL = 1<<4;
150 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800152 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
153 "com.android.defcontainer",
154 "com.android.defcontainer.DefaultContainerService");
155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
157 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700158 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159
Dianne Hackborn851a5412009-05-08 12:06:44 -0700160 final int mSdkVersion = Build.VERSION.SDK_INT;
161 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
162 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 final Context mContext;
165 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700166 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 final DisplayMetrics mMetrics;
168 final int mDefParseFlags;
169 final String[] mSeparateProcesses;
170
171 // This is where all application persistent data goes.
172 final File mAppDataDir;
173
Oscar Montemayora8529f62009-11-18 10:14:20 -0800174 // If Encrypted File System feature is enabled, all application persistent data
175 // should go here instead.
176 final File mSecureAppDataDir;
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 // This is the object monitoring the framework dir.
179 final FileObserver mFrameworkInstallObserver;
180
181 // This is the object monitoring the system app dir.
182 final FileObserver mSystemInstallObserver;
183
184 // This is the object monitoring mAppInstallDir.
185 final FileObserver mAppInstallObserver;
186
187 // This is the object monitoring mDrmAppPrivateInstallDir.
188 final FileObserver mDrmAppInstallObserver;
189
190 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
191 // LOCK HELD. Can be called with mInstallLock held.
192 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 final File mFrameworkDir;
195 final File mSystemAppDir;
196 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700197 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198
199 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
200 // apps.
201 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 // Lock for state used when installing and doing other long running
206 // operations. Methods that must be called with this lock held have
207 // the prefix "LI".
208 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // These are the directories in the 3rd party applications installed dir
211 // that we have currently loaded packages from. Keys are the application's
212 // installed zip file (absolute codePath), and values are Package.
213 final HashMap<String, PackageParser.Package> mAppDirs =
214 new HashMap<String, PackageParser.Package>();
215
216 // Information for the parser to write more useful error messages.
217 File mScanningPath;
218 int mLastScanError;
219
220 final int[] mOutPermissions = new int[3];
221
222 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 // Keys are String (package name), values are Package. This also serves
225 // as the lock for the global state. Methods that must be called with
226 // this lock held have the prefix "LP".
227 final HashMap<String, PackageParser.Package> mPackages =
228 new HashMap<String, PackageParser.Package>();
229
230 final Settings mSettings;
231 boolean mRestoredSettings;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
233 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
234 int[] mGlobalGids;
235
236 // These are the built-in uid -> permission mappings that were read from the
237 // etc/permissions.xml file.
238 final SparseArray<HashSet<String>> mSystemPermissions =
239 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 // These are the built-in shared libraries that were read from the
242 // etc/permissions.xml file.
243 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800244
Dianne Hackborn49237342009-08-27 20:08:01 -0700245 // Temporary for building the final shared libraries for an .apk.
246 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800247
Dianne Hackborn49237342009-08-27 20:08:01 -0700248 // These are the features this devices supports that were read from the
249 // etc/permissions.xml file.
250 final HashMap<String, FeatureInfo> mAvailableFeatures =
251 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 // All available activities, for your resolving pleasure.
254 final ActivityIntentResolver mActivities =
255 new ActivityIntentResolver();
256
257 // All available receivers, for your resolving pleasure.
258 final ActivityIntentResolver mReceivers =
259 new ActivityIntentResolver();
260
261 // All available services, for your resolving pleasure.
262 final ServiceIntentResolver mServices = new ServiceIntentResolver();
263
264 // Keys are String (provider class name), values are Provider.
265 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
266 new HashMap<ComponentName, PackageParser.Provider>();
267
268 // Mapping from provider base names (first directory in content URI codePath)
269 // to the provider information.
270 final HashMap<String, PackageParser.Provider> mProviders =
271 new HashMap<String, PackageParser.Provider>();
272
273 // Mapping from instrumentation class names to info about them.
274 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
275 new HashMap<ComponentName, PackageParser.Instrumentation>();
276
277 // Mapping from permission names to info about them.
278 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
279 new HashMap<String, PackageParser.PermissionGroup>();
280
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800281 // Packages whose data we have transfered into another package, thus
282 // should no longer exist.
283 final HashSet<String> mTransferedPackages = new HashSet<String>();
284
Dianne Hackborn854060af2009-07-09 18:14:31 -0700285 // Broadcast actions that are only available to the system.
286 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 boolean mSystemReady;
289 boolean mSafeMode;
290 boolean mHasSystemUidErrors;
291
292 ApplicationInfo mAndroidApplication;
293 final ActivityInfo mResolveActivity = new ActivityInfo();
294 final ResolveInfo mResolveInfo = new ResolveInfo();
295 ComponentName mResolveComponentName;
296 PackageParser.Package mPlatformPackage;
297
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700298 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800299 final HashMap<String, ArrayList<String>> mPendingBroadcasts
300 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700301 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800302 static final int MCS_BOUND = 3;
303 static final int END_COPY = 4;
304 static final int INIT_COPY = 5;
305 static final int MCS_UNBIND = 6;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800306 static final int START_CLEANING_PACKAGE = 7;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700307 // Delay time in millisecs
308 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800309 private ServiceConnection mDefContainerConn = new ServiceConnection() {
310 public void onServiceConnected(ComponentName name, IBinder service) {
311 IMediaContainerService imcs =
312 IMediaContainerService.Stub.asInterface(service);
313 Message msg = mHandler.obtainMessage(MCS_BOUND, imcs);
314 mHandler.sendMessage(msg);
315 }
316
317 public void onServiceDisconnected(ComponentName name) {
318 }
319 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700320
321 class PackageHandler extends Handler {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800322 final ArrayList<InstallArgs> mPendingInstalls =
323 new ArrayList<InstallArgs>();
324 // Service Connection to remote media container service to copy
325 // package uri's from external media onto secure containers
326 // or internal storage.
327 private IMediaContainerService mContainerService = null;
328
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700329 PackageHandler(Looper looper) {
330 super(looper);
331 }
332 public void handleMessage(Message msg) {
333 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800334 case INIT_COPY: {
335 InstallArgs args = (InstallArgs) msg.obj;
336 args.createCopyFile();
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800337 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800338 if (mContainerService != null) {
339 // No need to add to pending list. Use remote stub directly
340 handleStartCopy(args);
341 } else {
342 if (mContext.bindService(service, mDefContainerConn,
343 Context.BIND_AUTO_CREATE)) {
344 mPendingInstalls.add(args);
345 } else {
346 Log.e(TAG, "Failed to bind to media container service");
347 // Indicate install failure TODO add new error code
348 processPendingInstall(args,
349 PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800350 }
351 }
352 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800353 }
354 case MCS_BOUND: {
355 // Initialize mContainerService if needed.
356 if (msg.obj != null) {
357 mContainerService = (IMediaContainerService) msg.obj;
358 }
359 if (mPendingInstalls.size() > 0) {
360 InstallArgs args = mPendingInstalls.remove(0);
361 if (args != null) {
362 handleStartCopy(args);
363 }
364 }
365 break;
366 }
367 case MCS_UNBIND : {
368 if (mPendingInstalls.size() == 0) {
369 mContext.unbindService(mDefContainerConn);
370 mContainerService = null;
371 }
372 break;
373 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700374 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800375 String packages[];
376 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700377 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700378 int uids[];
379 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800380 if (mPendingBroadcasts == null) {
381 return;
382 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700383 size = mPendingBroadcasts.size();
384 if (size <= 0) {
385 // Nothing to be done. Just return
386 return;
387 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800388 packages = new String[size];
389 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700390 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800391 Iterator<HashMap.Entry<String, ArrayList<String>>>
392 it = mPendingBroadcasts.entrySet().iterator();
393 int i = 0;
394 while (it.hasNext() && i < size) {
395 HashMap.Entry<String, ArrayList<String>> ent = it.next();
396 packages[i] = ent.getKey();
397 components[i] = ent.getValue();
398 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700399 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800400 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700401 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800402 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700403 mPendingBroadcasts.clear();
404 }
405 // Send broadcasts
406 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800407 sendPackageChangedBroadcast(packages[i], true,
408 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700409 }
410 break;
411 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800412 case START_CLEANING_PACKAGE: {
413 String packageName = (String)msg.obj;
414 synchronized (mPackages) {
415 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) {
416 mSettings.mPackagesToBeCleaned.add(packageName);
417 }
418 }
419 startCleaningPackages();
420 } break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700421 }
422 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800423
424 // Utility method to initiate copying apk via media
425 // container service.
426 private void handleStartCopy(InstallArgs args) {
427 int ret = PackageManager.INSTALL_SUCCEEDED;
428 if (mContainerService == null) {
429 // Install error
430 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
431 } else {
432 ret = args.copyApk(mContainerService);
433 }
434 mHandler.sendEmptyMessage(MCS_UNBIND);
435 processPendingInstall(args, ret);
436 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700437 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800438
439 static boolean installOnSd(int flags) {
440 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
441 ((flags & PackageManager.INSTALL_ON_SDCARD) == 0)) {
442 return false;
443 }
444 return true;
445 }
446
447 static boolean isFwdLocked(int flags) {
448 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
449 return true;
450 }
451 return false;
452 }
453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 public static final IPackageManager main(Context context, boolean factoryTest) {
455 PackageManagerService m = new PackageManagerService(context, factoryTest);
456 ServiceManager.addService("package", m);
457 return m;
458 }
459
460 static String[] splitString(String str, char sep) {
461 int count = 1;
462 int i = 0;
463 while ((i=str.indexOf(sep, i)) >= 0) {
464 count++;
465 i++;
466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 String[] res = new String[count];
469 i=0;
470 count = 0;
471 int lastI=0;
472 while ((i=str.indexOf(sep, i)) >= 0) {
473 res[count] = str.substring(lastI, i);
474 count++;
475 i++;
476 lastI = i;
477 }
478 res[count] = str.substring(lastI, str.length());
479 return res;
480 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800483 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 if (mSdkVersion <= 0) {
487 Log.w(TAG, "**** ro.build.version.sdk not set!");
488 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 mContext = context;
491 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700492 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 mMetrics = new DisplayMetrics();
494 mSettings = new Settings();
495 mSettings.addSharedUserLP("android.uid.system",
496 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
497 mSettings.addSharedUserLP("android.uid.phone",
498 MULTIPLE_APPLICATION_UIDS
499 ? RADIO_UID : FIRST_APPLICATION_UID,
500 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400501 mSettings.addSharedUserLP("android.uid.log",
502 MULTIPLE_APPLICATION_UIDS
503 ? LOG_UID : FIRST_APPLICATION_UID,
504 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505
506 String separateProcesses = SystemProperties.get("debug.separate_processes");
507 if (separateProcesses != null && separateProcesses.length() > 0) {
508 if ("*".equals(separateProcesses)) {
509 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
510 mSeparateProcesses = null;
511 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
512 } else {
513 mDefParseFlags = 0;
514 mSeparateProcesses = separateProcesses.split(",");
515 Log.w(TAG, "Running with debug.separate_processes: "
516 + separateProcesses);
517 }
518 } else {
519 mDefParseFlags = 0;
520 mSeparateProcesses = null;
521 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 Installer installer = new Installer();
524 // Little hacky thing to check if installd is here, to determine
525 // whether we are running on the simulator and thus need to take
526 // care of building the /data file structure ourself.
527 // (apparently the sim now has a working installer)
528 if (installer.ping() && Process.supportsProcesses()) {
529 mInstaller = installer;
530 } else {
531 mInstaller = null;
532 }
533
534 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
535 Display d = wm.getDefaultDisplay();
536 d.getMetrics(mMetrics);
537
538 synchronized (mInstallLock) {
539 synchronized (mPackages) {
540 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700541 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 File dataDir = Environment.getDataDirectory();
544 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800545 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
547
548 if (mInstaller == null) {
549 // Make sure these dirs exist, when we are running in
550 // the simulator.
551 // Make a wide-open directory for random misc stuff.
552 File miscDir = new File(dataDir, "misc");
553 miscDir.mkdirs();
554 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800555 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 mDrmAppPrivateInstallDir.mkdirs();
557 }
558
559 readPermissions();
560
561 mRestoredSettings = mSettings.readLP();
562 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800563
564 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800566
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800567 // Set flag to monitor and not change apk file paths when
568 // scanning install directories.
569 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700570 if (mNoDexOpt) {
571 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800572 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700573 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700578 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700581 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 /**
584 * Out of paranoia, ensure that everything in the boot class
585 * path has been dexed.
586 */
587 String bootClassPath = System.getProperty("java.boot.class.path");
588 if (bootClassPath != null) {
589 String[] paths = splitString(bootClassPath, ':');
590 for (int i=0; i<paths.length; i++) {
591 try {
592 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
593 libFiles.add(paths[i]);
594 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700595 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 }
597 } catch (FileNotFoundException e) {
598 Log.w(TAG, "Boot class path not found: " + paths[i]);
599 } catch (IOException e) {
600 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
601 }
602 }
603 } else {
604 Log.w(TAG, "No BOOTCLASSPATH found!");
605 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 /**
608 * Also ensure all external libraries have had dexopt run on them.
609 */
610 if (mSharedLibraries.size() > 0) {
611 Iterator<String> libs = mSharedLibraries.values().iterator();
612 while (libs.hasNext()) {
613 String lib = libs.next();
614 try {
615 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
616 libFiles.add(lib);
617 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700618 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 }
620 } catch (FileNotFoundException e) {
621 Log.w(TAG, "Library not found: " + lib);
622 } catch (IOException e) {
623 Log.w(TAG, "Exception reading library: " + lib, e);
624 }
625 }
626 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 // Gross hack for now: we know this file doesn't contain any
629 // code, so don't dexopt it to avoid the resulting log spew.
630 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 /**
633 * And there are a number of commands implemented in Java, which
634 * we currently need to do the dexopt on so that they can be
635 * run from a non-root shell.
636 */
637 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700638 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 for (int i=0; i<frameworkFiles.length; i++) {
640 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
641 String path = libPath.getPath();
642 // Skip the file if we alrady did it.
643 if (libFiles.contains(path)) {
644 continue;
645 }
646 // Skip the file if it is not a type we want to dexopt.
647 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
648 continue;
649 }
650 try {
651 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
652 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700653 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 }
655 } catch (FileNotFoundException e) {
656 Log.w(TAG, "Jar not found: " + path);
657 } catch (IOException e) {
658 Log.w(TAG, "Exception reading jar: " + path, e);
659 }
660 }
661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800662
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700663 if (didDexOpt) {
664 // If we had to do a dexopt of one of the previous
665 // things, then something on the system has changed.
666 // Consider this significant, and wipe away all other
667 // existing dexopt files to ensure we don't leave any
668 // dangling around.
669 String[] files = mDalvikCacheDir.list();
670 if (files != null) {
671 for (int i=0; i<files.length; i++) {
672 String fn = files[i];
673 if (fn.startsWith("data@app@")
674 || fn.startsWith("data@app-private@")) {
675 Log.i(TAG, "Pruning dalvik file: " + fn);
676 (new File(mDalvikCacheDir, fn)).delete();
677 }
678 }
679 }
680 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800682
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800683 // Find base frameworks (resource packages without code).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 mFrameworkInstallObserver = new AppDirObserver(
685 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
686 mFrameworkInstallObserver.startWatching();
687 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800688 scanMode | SCAN_NO_DEX);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800689
690 // Collect all system packages.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
692 mSystemInstallObserver = new AppDirObserver(
693 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
694 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800695 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -0800696
697 if (mInstaller != null) {
698 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
699 mInstaller.moveFiles();
700 }
701
702 // Prune any system packages that no longer exist.
703 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
704 while (psit.hasNext()) {
705 PackageSetting ps = psit.next();
706 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
707 && !mPackages.containsKey(ps.name)) {
708 psit.remove();
709 String msg = "System package " + ps.name
710 + " no longer exists; wiping its data";
711 reportSettingsProblem(Log.WARN, msg);
712 if (mInstaller != null) {
713 // XXX how to set useEncryptedFSDir for packages that
714 // are not encrypted?
715 mInstaller.remove(ps.name, true);
716 }
717 }
718 }
719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 mAppInstallDir = new File(dataDir, "app");
721 if (mInstaller == null) {
722 // Make sure these dirs exist, when we are running in
723 // the simulator.
724 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
725 }
726 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800727 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 //clean up list
729 for(int i = 0; i < deletePkgsList.size(); i++) {
730 //clean up here
731 cleanupInstallFailedPackage(deletePkgsList.get(i));
732 }
733 //delete tmp files
734 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800735
736 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 SystemClock.uptimeMillis());
738 mAppInstallObserver = new AppDirObserver(
739 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
740 mAppInstallObserver.startWatching();
741 scanDirLI(mAppInstallDir, 0, scanMode);
742
743 mDrmAppInstallObserver = new AppDirObserver(
744 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
745 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800746 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800748 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 SystemClock.uptimeMillis());
750 Log.i(TAG, "Time to scan packages: "
751 + ((SystemClock.uptimeMillis()-startTime)/1000f)
752 + " seconds");
753
754 updatePermissionsLP();
755
756 mSettings.writeLP();
757
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800758 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 // Now after opening every single application zip, make sure they
762 // are all flushed. Not really needed, but keeps things nice and
763 // tidy.
764 Runtime.getRuntime().gc();
765 } // synchronized (mPackages)
766 } // synchronized (mInstallLock)
767 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 @Override
770 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
771 throws RemoteException {
772 try {
773 return super.onTransact(code, data, reply, flags);
774 } catch (RuntimeException e) {
775 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
776 Log.e(TAG, "Package Manager Crash", e);
777 }
778 throw e;
779 }
780 }
781
Dianne Hackborne6620b22010-01-22 14:46:21 -0800782 void cleanupInstallFailedPackage(PackageSetting ps) {
783 Log.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 if (mInstaller != null) {
Kenny Rootbdbc9252010-01-28 12:03:49 -0800785 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
786 int retCode = mInstaller.remove(ps.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 if (retCode < 0) {
788 Log.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800789 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 }
791 } else {
792 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800793 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 File dataDir = new File(pkg.applicationInfo.dataDir);
795 dataDir.delete();
796 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800797 if (ps.codePath != null) {
798 if (!ps.codePath.delete()) {
799 Log.w(TAG, "Unable to remove old code file: " + ps.codePath);
800 }
801 }
802 if (ps.resourcePath != null) {
803 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
804 Log.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
805 }
806 }
807 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 }
809
810 void readPermissions() {
811 // Read permissions from .../etc/permission directory.
812 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
813 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
814 Log.w(TAG, "No directory " + libraryDir + ", skipping");
815 return;
816 }
817 if (!libraryDir.canRead()) {
818 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
819 return;
820 }
821
822 // Iterate over the files in the directory and scan .xml files
823 for (File f : libraryDir.listFiles()) {
824 // We'll read platform.xml last
825 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
826 continue;
827 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 if (!f.getPath().endsWith(".xml")) {
830 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
831 continue;
832 }
833 if (!f.canRead()) {
834 Log.w(TAG, "Permissions library file " + f + " cannot be read");
835 continue;
836 }
837
838 readPermissionsFromXml(f);
839 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
842 final File permFile = new File(Environment.getRootDirectory(),
843 "etc/permissions/platform.xml");
844 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800845
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700846 StringBuilder sb = new StringBuilder(128);
847 sb.append("Libs:");
848 Iterator<String> it = mSharedLibraries.keySet().iterator();
849 while (it.hasNext()) {
850 sb.append(' ');
851 String name = it.next();
852 sb.append(name);
853 sb.append(':');
854 sb.append(mSharedLibraries.get(name));
855 }
856 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800857
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700858 sb.setLength(0);
859 sb.append("Features:");
860 it = mAvailableFeatures.keySet().iterator();
861 while (it.hasNext()) {
862 sb.append(' ');
863 sb.append(it.next());
864 }
865 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800867
868 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 FileReader permReader = null;
870 try {
871 permReader = new FileReader(permFile);
872 } catch (FileNotFoundException e) {
873 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
874 return;
875 }
876
877 try {
878 XmlPullParser parser = Xml.newPullParser();
879 parser.setInput(permReader);
880
881 XmlUtils.beginDocument(parser, "permissions");
882
883 while (true) {
884 XmlUtils.nextElement(parser);
885 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
886 break;
887 }
888
889 String name = parser.getName();
890 if ("group".equals(name)) {
891 String gidStr = parser.getAttributeValue(null, "gid");
892 if (gidStr != null) {
893 int gid = Integer.parseInt(gidStr);
894 mGlobalGids = appendInt(mGlobalGids, gid);
895 } else {
896 Log.w(TAG, "<group> without gid at "
897 + parser.getPositionDescription());
898 }
899
900 XmlUtils.skipCurrentTag(parser);
901 continue;
902 } else if ("permission".equals(name)) {
903 String perm = parser.getAttributeValue(null, "name");
904 if (perm == null) {
905 Log.w(TAG, "<permission> without name at "
906 + parser.getPositionDescription());
907 XmlUtils.skipCurrentTag(parser);
908 continue;
909 }
910 perm = perm.intern();
911 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 } else if ("assign-permission".equals(name)) {
914 String perm = parser.getAttributeValue(null, "name");
915 if (perm == null) {
916 Log.w(TAG, "<assign-permission> without name at "
917 + parser.getPositionDescription());
918 XmlUtils.skipCurrentTag(parser);
919 continue;
920 }
921 String uidStr = parser.getAttributeValue(null, "uid");
922 if (uidStr == null) {
923 Log.w(TAG, "<assign-permission> without uid at "
924 + parser.getPositionDescription());
925 XmlUtils.skipCurrentTag(parser);
926 continue;
927 }
928 int uid = Process.getUidForName(uidStr);
929 if (uid < 0) {
930 Log.w(TAG, "<assign-permission> with unknown uid \""
931 + uidStr + "\" at "
932 + parser.getPositionDescription());
933 XmlUtils.skipCurrentTag(parser);
934 continue;
935 }
936 perm = perm.intern();
937 HashSet<String> perms = mSystemPermissions.get(uid);
938 if (perms == null) {
939 perms = new HashSet<String>();
940 mSystemPermissions.put(uid, perms);
941 }
942 perms.add(perm);
943 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 } else if ("library".equals(name)) {
946 String lname = parser.getAttributeValue(null, "name");
947 String lfile = parser.getAttributeValue(null, "file");
948 if (lname == null) {
949 Log.w(TAG, "<library> without name at "
950 + parser.getPositionDescription());
951 } else if (lfile == null) {
952 Log.w(TAG, "<library> without file at "
953 + parser.getPositionDescription());
954 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700955 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700956 mSharedLibraries.put(lname, lfile);
957 }
958 XmlUtils.skipCurrentTag(parser);
959 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800960
Dianne Hackborn49237342009-08-27 20:08:01 -0700961 } else if ("feature".equals(name)) {
962 String fname = parser.getAttributeValue(null, "name");
963 if (fname == null) {
964 Log.w(TAG, "<feature> without name at "
965 + parser.getPositionDescription());
966 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700967 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700968 FeatureInfo fi = new FeatureInfo();
969 fi.name = fname;
970 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 }
972 XmlUtils.skipCurrentTag(parser);
973 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } else {
976 XmlUtils.skipCurrentTag(parser);
977 continue;
978 }
979
980 }
981 } catch (XmlPullParserException e) {
982 Log.w(TAG, "Got execption parsing permissions.", e);
983 } catch (IOException e) {
984 Log.w(TAG, "Got execption parsing permissions.", e);
985 }
986 }
987
988 void readPermission(XmlPullParser parser, String name)
989 throws IOException, XmlPullParserException {
990
991 name = name.intern();
992
993 BasePermission bp = mSettings.mPermissions.get(name);
994 if (bp == null) {
995 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
996 mSettings.mPermissions.put(name, bp);
997 }
998 int outerDepth = parser.getDepth();
999 int type;
1000 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1001 && (type != XmlPullParser.END_TAG
1002 || parser.getDepth() > outerDepth)) {
1003 if (type == XmlPullParser.END_TAG
1004 || type == XmlPullParser.TEXT) {
1005 continue;
1006 }
1007
1008 String tagName = parser.getName();
1009 if ("group".equals(tagName)) {
1010 String gidStr = parser.getAttributeValue(null, "gid");
1011 if (gidStr != null) {
1012 int gid = Process.getGidForName(gidStr);
1013 bp.gids = appendInt(bp.gids, gid);
1014 } else {
1015 Log.w(TAG, "<group> without gid at "
1016 + parser.getPositionDescription());
1017 }
1018 }
1019 XmlUtils.skipCurrentTag(parser);
1020 }
1021 }
1022
1023 static int[] appendInt(int[] cur, int val) {
1024 if (cur == null) {
1025 return new int[] { val };
1026 }
1027 final int N = cur.length;
1028 for (int i=0; i<N; i++) {
1029 if (cur[i] == val) {
1030 return cur;
1031 }
1032 }
1033 int[] ret = new int[N+1];
1034 System.arraycopy(cur, 0, ret, 0, N);
1035 ret[N] = val;
1036 return ret;
1037 }
1038
1039 static int[] appendInts(int[] cur, int[] add) {
1040 if (add == null) return cur;
1041 if (cur == null) return add;
1042 final int N = add.length;
1043 for (int i=0; i<N; i++) {
1044 cur = appendInt(cur, add[i]);
1045 }
1046 return cur;
1047 }
1048
1049 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001050 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1051 // The package has been uninstalled but has retained data and resources.
1052 return PackageParser.generatePackageInfo(p, null, flags);
1053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 final PackageSetting ps = (PackageSetting)p.mExtras;
1055 if (ps == null) {
1056 return null;
1057 }
1058 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1059 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1060 }
1061
1062 public PackageInfo getPackageInfo(String packageName, int flags) {
1063 synchronized (mPackages) {
1064 PackageParser.Package p = mPackages.get(packageName);
1065 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001066 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 + ": " + p);
1068 if (p != null) {
1069 return generatePackageInfo(p, flags);
1070 }
1071 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1072 return generatePackageInfoFromSettingsLP(packageName, flags);
1073 }
1074 }
1075 return null;
1076 }
1077
1078 public int getPackageUid(String packageName) {
1079 synchronized (mPackages) {
1080 PackageParser.Package p = mPackages.get(packageName);
1081 if(p != null) {
1082 return p.applicationInfo.uid;
1083 }
1084 PackageSetting ps = mSettings.mPackages.get(packageName);
1085 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1086 return -1;
1087 }
1088 p = ps.pkg;
1089 return p != null ? p.applicationInfo.uid : -1;
1090 }
1091 }
1092
1093 public int[] getPackageGids(String packageName) {
1094 synchronized (mPackages) {
1095 PackageParser.Package p = mPackages.get(packageName);
1096 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001097 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 + ": " + p);
1099 if (p != null) {
1100 final PackageSetting ps = (PackageSetting)p.mExtras;
1101 final SharedUserSetting suid = ps.sharedUser;
1102 return suid != null ? suid.gids : ps.gids;
1103 }
1104 }
1105 // stupid thing to indicate an error.
1106 return new int[0];
1107 }
1108
1109 public PermissionInfo getPermissionInfo(String name, int flags) {
1110 synchronized (mPackages) {
1111 final BasePermission p = mSettings.mPermissions.get(name);
1112 if (p != null && p.perm != null) {
1113 return PackageParser.generatePermissionInfo(p.perm, flags);
1114 }
1115 return null;
1116 }
1117 }
1118
1119 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1120 synchronized (mPackages) {
1121 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1122 for (BasePermission p : mSettings.mPermissions.values()) {
1123 if (group == null) {
1124 if (p.perm.info.group == null) {
1125 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1126 }
1127 } else {
1128 if (group.equals(p.perm.info.group)) {
1129 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1130 }
1131 }
1132 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 if (out.size() > 0) {
1135 return out;
1136 }
1137 return mPermissionGroups.containsKey(group) ? out : null;
1138 }
1139 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1142 synchronized (mPackages) {
1143 return PackageParser.generatePermissionGroupInfo(
1144 mPermissionGroups.get(name), flags);
1145 }
1146 }
1147
1148 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1149 synchronized (mPackages) {
1150 final int N = mPermissionGroups.size();
1151 ArrayList<PermissionGroupInfo> out
1152 = new ArrayList<PermissionGroupInfo>(N);
1153 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1154 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1155 }
1156 return out;
1157 }
1158 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1161 PackageSetting ps = mSettings.mPackages.get(packageName);
1162 if(ps != null) {
1163 if(ps.pkg == null) {
1164 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1165 if(pInfo != null) {
1166 return pInfo.applicationInfo;
1167 }
1168 return null;
1169 }
1170 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1171 }
1172 return null;
1173 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1176 PackageSetting ps = mSettings.mPackages.get(packageName);
1177 if(ps != null) {
1178 if(ps.pkg == null) {
1179 ps.pkg = new PackageParser.Package(packageName);
1180 ps.pkg.applicationInfo.packageName = packageName;
1181 }
1182 return generatePackageInfo(ps.pkg, flags);
1183 }
1184 return null;
1185 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1188 synchronized (mPackages) {
1189 PackageParser.Package p = mPackages.get(packageName);
1190 if (Config.LOGV) Log.v(
1191 TAG, "getApplicationInfo " + packageName
1192 + ": " + p);
1193 if (p != null) {
1194 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001195 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 }
1197 if ("android".equals(packageName)||"system".equals(packageName)) {
1198 return mAndroidApplication;
1199 }
1200 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1201 return generateApplicationInfoFromSettingsLP(packageName, flags);
1202 }
1203 }
1204 return null;
1205 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001206
1207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1209 mContext.enforceCallingOrSelfPermission(
1210 android.Manifest.permission.CLEAR_APP_CACHE, null);
1211 // Queue up an async operation since clearing cache may take a little while.
1212 mHandler.post(new Runnable() {
1213 public void run() {
1214 mHandler.removeCallbacks(this);
1215 int retCode = -1;
1216 if (mInstaller != null) {
1217 retCode = mInstaller.freeCache(freeStorageSize);
1218 if (retCode < 0) {
1219 Log.w(TAG, "Couldn't clear application caches");
1220 }
1221 } //end if mInstaller
1222 if (observer != null) {
1223 try {
1224 observer.onRemoveCompleted(null, (retCode >= 0));
1225 } catch (RemoteException e) {
1226 Log.w(TAG, "RemoveException when invoking call back");
1227 }
1228 }
1229 }
1230 });
1231 }
1232
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001233 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001234 mContext.enforceCallingOrSelfPermission(
1235 android.Manifest.permission.CLEAR_APP_CACHE, null);
1236 // Queue up an async operation since clearing cache may take a little while.
1237 mHandler.post(new Runnable() {
1238 public void run() {
1239 mHandler.removeCallbacks(this);
1240 int retCode = -1;
1241 if (mInstaller != null) {
1242 retCode = mInstaller.freeCache(freeStorageSize);
1243 if (retCode < 0) {
1244 Log.w(TAG, "Couldn't clear application caches");
1245 }
1246 }
1247 if(pi != null) {
1248 try {
1249 // Callback via pending intent
1250 int code = (retCode >= 0) ? 1 : 0;
1251 pi.sendIntent(null, code, null,
1252 null, null);
1253 } catch (SendIntentException e1) {
1254 Log.i(TAG, "Failed to send pending intent");
1255 }
1256 }
1257 }
1258 });
1259 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1262 synchronized (mPackages) {
1263 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001264
1265 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001267 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 }
1269 if (mResolveComponentName.equals(component)) {
1270 return mResolveActivity;
1271 }
1272 }
1273 return null;
1274 }
1275
1276 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1277 synchronized (mPackages) {
1278 PackageParser.Activity a = mReceivers.mActivities.get(component);
1279 if (Config.LOGV) Log.v(
1280 TAG, "getReceiverInfo " + component + ": " + a);
1281 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1282 return PackageParser.generateActivityInfo(a, flags);
1283 }
1284 }
1285 return null;
1286 }
1287
1288 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1289 synchronized (mPackages) {
1290 PackageParser.Service s = mServices.mServices.get(component);
1291 if (Config.LOGV) Log.v(
1292 TAG, "getServiceInfo " + component + ": " + s);
1293 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1294 return PackageParser.generateServiceInfo(s, flags);
1295 }
1296 }
1297 return null;
1298 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001300 public String[] getSystemSharedLibraryNames() {
1301 Set<String> libSet;
1302 synchronized (mPackages) {
1303 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001304 int size = libSet.size();
1305 if (size > 0) {
1306 String[] libs = new String[size];
1307 libSet.toArray(libs);
1308 return libs;
1309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001311 return null;
1312 }
1313
1314 public FeatureInfo[] getSystemAvailableFeatures() {
1315 Collection<FeatureInfo> featSet;
1316 synchronized (mPackages) {
1317 featSet = mAvailableFeatures.values();
1318 int size = featSet.size();
1319 if (size > 0) {
1320 FeatureInfo[] features = new FeatureInfo[size+1];
1321 featSet.toArray(features);
1322 FeatureInfo fi = new FeatureInfo();
1323 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1324 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1325 features[size] = fi;
1326 return features;
1327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 }
1329 return null;
1330 }
1331
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001332 public boolean hasSystemFeature(String name) {
1333 synchronized (mPackages) {
1334 return mAvailableFeatures.containsKey(name);
1335 }
1336 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 public int checkPermission(String permName, String pkgName) {
1339 synchronized (mPackages) {
1340 PackageParser.Package p = mPackages.get(pkgName);
1341 if (p != null && p.mExtras != null) {
1342 PackageSetting ps = (PackageSetting)p.mExtras;
1343 if (ps.sharedUser != null) {
1344 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1345 return PackageManager.PERMISSION_GRANTED;
1346 }
1347 } else if (ps.grantedPermissions.contains(permName)) {
1348 return PackageManager.PERMISSION_GRANTED;
1349 }
1350 }
1351 }
1352 return PackageManager.PERMISSION_DENIED;
1353 }
1354
1355 public int checkUidPermission(String permName, int uid) {
1356 synchronized (mPackages) {
1357 Object obj = mSettings.getUserIdLP(uid);
1358 if (obj != null) {
1359 if (obj instanceof SharedUserSetting) {
1360 SharedUserSetting sus = (SharedUserSetting)obj;
1361 if (sus.grantedPermissions.contains(permName)) {
1362 return PackageManager.PERMISSION_GRANTED;
1363 }
1364 } else if (obj instanceof PackageSetting) {
1365 PackageSetting ps = (PackageSetting)obj;
1366 if (ps.grantedPermissions.contains(permName)) {
1367 return PackageManager.PERMISSION_GRANTED;
1368 }
1369 }
1370 } else {
1371 HashSet<String> perms = mSystemPermissions.get(uid);
1372 if (perms != null && perms.contains(permName)) {
1373 return PackageManager.PERMISSION_GRANTED;
1374 }
1375 }
1376 }
1377 return PackageManager.PERMISSION_DENIED;
1378 }
1379
1380 private BasePermission findPermissionTreeLP(String permName) {
1381 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1382 if (permName.startsWith(bp.name) &&
1383 permName.length() > bp.name.length() &&
1384 permName.charAt(bp.name.length()) == '.') {
1385 return bp;
1386 }
1387 }
1388 return null;
1389 }
1390
1391 private BasePermission checkPermissionTreeLP(String permName) {
1392 if (permName != null) {
1393 BasePermission bp = findPermissionTreeLP(permName);
1394 if (bp != null) {
1395 if (bp.uid == Binder.getCallingUid()) {
1396 return bp;
1397 }
1398 throw new SecurityException("Calling uid "
1399 + Binder.getCallingUid()
1400 + " is not allowed to add to permission tree "
1401 + bp.name + " owned by uid " + bp.uid);
1402 }
1403 }
1404 throw new SecurityException("No permission tree found for " + permName);
1405 }
1406
1407 public boolean addPermission(PermissionInfo info) {
1408 synchronized (mPackages) {
1409 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1410 throw new SecurityException("Label must be specified in permission");
1411 }
1412 BasePermission tree = checkPermissionTreeLP(info.name);
1413 BasePermission bp = mSettings.mPermissions.get(info.name);
1414 boolean added = bp == null;
1415 if (added) {
1416 bp = new BasePermission(info.name, tree.sourcePackage,
1417 BasePermission.TYPE_DYNAMIC);
1418 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1419 throw new SecurityException(
1420 "Not allowed to modify non-dynamic permission "
1421 + info.name);
1422 }
1423 bp.perm = new PackageParser.Permission(tree.perm.owner,
1424 new PermissionInfo(info));
1425 bp.perm.info.packageName = tree.perm.info.packageName;
1426 bp.uid = tree.uid;
1427 if (added) {
1428 mSettings.mPermissions.put(info.name, bp);
1429 }
1430 mSettings.writeLP();
1431 return added;
1432 }
1433 }
1434
1435 public void removePermission(String name) {
1436 synchronized (mPackages) {
1437 checkPermissionTreeLP(name);
1438 BasePermission bp = mSettings.mPermissions.get(name);
1439 if (bp != null) {
1440 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1441 throw new SecurityException(
1442 "Not allowed to modify non-dynamic permission "
1443 + name);
1444 }
1445 mSettings.mPermissions.remove(name);
1446 mSettings.writeLP();
1447 }
1448 }
1449 }
1450
Dianne Hackborn854060af2009-07-09 18:14:31 -07001451 public boolean isProtectedBroadcast(String actionName) {
1452 synchronized (mPackages) {
1453 return mProtectedBroadcasts.contains(actionName);
1454 }
1455 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 public int checkSignatures(String pkg1, String pkg2) {
1458 synchronized (mPackages) {
1459 PackageParser.Package p1 = mPackages.get(pkg1);
1460 PackageParser.Package p2 = mPackages.get(pkg2);
1461 if (p1 == null || p1.mExtras == null
1462 || p2 == null || p2.mExtras == null) {
1463 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1464 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001465 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467 }
1468
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001469 public int checkUidSignatures(int uid1, int uid2) {
1470 synchronized (mPackages) {
1471 Signature[] s1;
1472 Signature[] s2;
1473 Object obj = mSettings.getUserIdLP(uid1);
1474 if (obj != null) {
1475 if (obj instanceof SharedUserSetting) {
1476 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1477 } else if (obj instanceof PackageSetting) {
1478 s1 = ((PackageSetting)obj).signatures.mSignatures;
1479 } else {
1480 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1481 }
1482 } else {
1483 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1484 }
1485 obj = mSettings.getUserIdLP(uid2);
1486 if (obj != null) {
1487 if (obj instanceof SharedUserSetting) {
1488 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1489 } else if (obj instanceof PackageSetting) {
1490 s2 = ((PackageSetting)obj).signatures.mSignatures;
1491 } else {
1492 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1493 }
1494 } else {
1495 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1496 }
1497 return checkSignaturesLP(s1, s2);
1498 }
1499 }
1500
1501 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1502 if (s1 == null) {
1503 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1505 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1506 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001507 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1509 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001510 final int N1 = s1.length;
1511 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 for (int i=0; i<N1; i++) {
1513 boolean match = false;
1514 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001515 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 match = true;
1517 break;
1518 }
1519 }
1520 if (!match) {
1521 return PackageManager.SIGNATURE_NO_MATCH;
1522 }
1523 }
1524 return PackageManager.SIGNATURE_MATCH;
1525 }
1526
1527 public String[] getPackagesForUid(int uid) {
1528 synchronized (mPackages) {
1529 Object obj = mSettings.getUserIdLP(uid);
1530 if (obj instanceof SharedUserSetting) {
1531 SharedUserSetting sus = (SharedUserSetting)obj;
1532 final int N = sus.packages.size();
1533 String[] res = new String[N];
1534 Iterator<PackageSetting> it = sus.packages.iterator();
1535 int i=0;
1536 while (it.hasNext()) {
1537 res[i++] = it.next().name;
1538 }
1539 return res;
1540 } else if (obj instanceof PackageSetting) {
1541 PackageSetting ps = (PackageSetting)obj;
1542 return new String[] { ps.name };
1543 }
1544 }
1545 return null;
1546 }
1547
1548 public String getNameForUid(int uid) {
1549 synchronized (mPackages) {
1550 Object obj = mSettings.getUserIdLP(uid);
1551 if (obj instanceof SharedUserSetting) {
1552 SharedUserSetting sus = (SharedUserSetting)obj;
1553 return sus.name + ":" + sus.userId;
1554 } else if (obj instanceof PackageSetting) {
1555 PackageSetting ps = (PackageSetting)obj;
1556 return ps.name;
1557 }
1558 }
1559 return null;
1560 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 public int getUidForSharedUser(String sharedUserName) {
1563 if(sharedUserName == null) {
1564 return -1;
1565 }
1566 synchronized (mPackages) {
1567 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1568 if(suid == null) {
1569 return -1;
1570 }
1571 return suid.userId;
1572 }
1573 }
1574
1575 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1576 int flags) {
1577 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001578 return chooseBestActivity(intent, resolvedType, flags, query);
1579 }
1580
Mihai Predaeae850c2009-05-13 10:13:48 +02001581 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1582 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 if (query != null) {
1584 final int N = query.size();
1585 if (N == 1) {
1586 return query.get(0);
1587 } else if (N > 1) {
1588 // If there is more than one activity with the same priority,
1589 // then let the user decide between them.
1590 ResolveInfo r0 = query.get(0);
1591 ResolveInfo r1 = query.get(1);
1592 if (false) {
1593 System.out.println(r0.activityInfo.name +
1594 "=" + r0.priority + " vs " +
1595 r1.activityInfo.name +
1596 "=" + r1.priority);
1597 }
1598 // If the first activity has a higher priority, or a different
1599 // default, then it is always desireable to pick it.
1600 if (r0.priority != r1.priority
1601 || r0.preferredOrder != r1.preferredOrder
1602 || r0.isDefault != r1.isDefault) {
1603 return query.get(0);
1604 }
1605 // If we have saved a preference for a preferred activity for
1606 // this Intent, use that.
1607 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1608 flags, query, r0.priority);
1609 if (ri != null) {
1610 return ri;
1611 }
1612 return mResolveInfo;
1613 }
1614 }
1615 return null;
1616 }
1617
1618 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1619 int flags, List<ResolveInfo> query, int priority) {
1620 synchronized (mPackages) {
1621 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1622 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001623 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1625 if (prefs != null && prefs.size() > 0) {
1626 // First figure out how good the original match set is.
1627 // We will only allow preferred activities that came
1628 // from the same match quality.
1629 int match = 0;
1630 final int N = query.size();
1631 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1632 for (int j=0; j<N; j++) {
1633 ResolveInfo ri = query.get(j);
1634 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1635 + ": 0x" + Integer.toHexString(match));
1636 if (ri.match > match) match = ri.match;
1637 }
1638 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1639 + Integer.toHexString(match));
1640 match &= IntentFilter.MATCH_CATEGORY_MASK;
1641 final int M = prefs.size();
1642 for (int i=0; i<M; i++) {
1643 PreferredActivity pa = prefs.get(i);
1644 if (pa.mMatch != match) {
1645 continue;
1646 }
1647 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1648 if (DEBUG_PREFERRED) {
1649 Log.v(TAG, "Got preferred activity:");
1650 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1651 }
1652 if (ai != null) {
1653 for (int j=0; j<N; j++) {
1654 ResolveInfo ri = query.get(j);
1655 if (!ri.activityInfo.applicationInfo.packageName
1656 .equals(ai.applicationInfo.packageName)) {
1657 continue;
1658 }
1659 if (!ri.activityInfo.name.equals(ai.name)) {
1660 continue;
1661 }
1662
1663 // Okay we found a previously set preferred app.
1664 // If the result set is different from when this
1665 // was created, we need to clear it and re-ask the
1666 // user their preference.
1667 if (!pa.sameSet(query, priority)) {
1668 Log.i(TAG, "Result set changed, dropping preferred activity for "
1669 + intent + " type " + resolvedType);
1670 mSettings.mPreferredActivities.removeFilter(pa);
1671 return null;
1672 }
1673
1674 // Yay!
1675 return ri;
1676 }
1677 }
1678 }
1679 }
1680 }
1681 return null;
1682 }
1683
1684 public List<ResolveInfo> queryIntentActivities(Intent intent,
1685 String resolvedType, int flags) {
1686 ComponentName comp = intent.getComponent();
1687 if (comp != null) {
1688 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1689 ActivityInfo ai = getActivityInfo(comp, flags);
1690 if (ai != null) {
1691 ResolveInfo ri = new ResolveInfo();
1692 ri.activityInfo = ai;
1693 list.add(ri);
1694 }
1695 return list;
1696 }
1697
1698 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001699 String pkgName = intent.getPackage();
1700 if (pkgName == null) {
1701 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1702 resolvedType, flags);
1703 }
1704 PackageParser.Package pkg = mPackages.get(pkgName);
1705 if (pkg != null) {
1706 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1707 resolvedType, flags, pkg.activities);
1708 }
1709 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 }
1711 }
1712
1713 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1714 Intent[] specifics, String[] specificTypes, Intent intent,
1715 String resolvedType, int flags) {
1716 final String resultsAction = intent.getAction();
1717
1718 List<ResolveInfo> results = queryIntentActivities(
1719 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1720 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1721
1722 int specificsPos = 0;
1723 int N;
1724
1725 // todo: note that the algorithm used here is O(N^2). This
1726 // isn't a problem in our current environment, but if we start running
1727 // into situations where we have more than 5 or 10 matches then this
1728 // should probably be changed to something smarter...
1729
1730 // First we go through and resolve each of the specific items
1731 // that were supplied, taking care of removing any corresponding
1732 // duplicate items in the generic resolve list.
1733 if (specifics != null) {
1734 for (int i=0; i<specifics.length; i++) {
1735 final Intent sintent = specifics[i];
1736 if (sintent == null) {
1737 continue;
1738 }
1739
1740 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1741 String action = sintent.getAction();
1742 if (resultsAction != null && resultsAction.equals(action)) {
1743 // If this action was explicitly requested, then don't
1744 // remove things that have it.
1745 action = null;
1746 }
1747 ComponentName comp = sintent.getComponent();
1748 ResolveInfo ri = null;
1749 ActivityInfo ai = null;
1750 if (comp == null) {
1751 ri = resolveIntent(
1752 sintent,
1753 specificTypes != null ? specificTypes[i] : null,
1754 flags);
1755 if (ri == null) {
1756 continue;
1757 }
1758 if (ri == mResolveInfo) {
1759 // ACK! Must do something better with this.
1760 }
1761 ai = ri.activityInfo;
1762 comp = new ComponentName(ai.applicationInfo.packageName,
1763 ai.name);
1764 } else {
1765 ai = getActivityInfo(comp, flags);
1766 if (ai == null) {
1767 continue;
1768 }
1769 }
1770
1771 // Look for any generic query activities that are duplicates
1772 // of this specific one, and remove them from the results.
1773 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1774 N = results.size();
1775 int j;
1776 for (j=specificsPos; j<N; j++) {
1777 ResolveInfo sri = results.get(j);
1778 if ((sri.activityInfo.name.equals(comp.getClassName())
1779 && sri.activityInfo.applicationInfo.packageName.equals(
1780 comp.getPackageName()))
1781 || (action != null && sri.filter.matchAction(action))) {
1782 results.remove(j);
1783 if (Config.LOGV) Log.v(
1784 TAG, "Removing duplicate item from " + j
1785 + " due to specific " + specificsPos);
1786 if (ri == null) {
1787 ri = sri;
1788 }
1789 j--;
1790 N--;
1791 }
1792 }
1793
1794 // Add this specific item to its proper place.
1795 if (ri == null) {
1796 ri = new ResolveInfo();
1797 ri.activityInfo = ai;
1798 }
1799 results.add(specificsPos, ri);
1800 ri.specificIndex = i;
1801 specificsPos++;
1802 }
1803 }
1804
1805 // Now we go through the remaining generic results and remove any
1806 // duplicate actions that are found here.
1807 N = results.size();
1808 for (int i=specificsPos; i<N-1; i++) {
1809 final ResolveInfo rii = results.get(i);
1810 if (rii.filter == null) {
1811 continue;
1812 }
1813
1814 // Iterate over all of the actions of this result's intent
1815 // filter... typically this should be just one.
1816 final Iterator<String> it = rii.filter.actionsIterator();
1817 if (it == null) {
1818 continue;
1819 }
1820 while (it.hasNext()) {
1821 final String action = it.next();
1822 if (resultsAction != null && resultsAction.equals(action)) {
1823 // If this action was explicitly requested, then don't
1824 // remove things that have it.
1825 continue;
1826 }
1827 for (int j=i+1; j<N; j++) {
1828 final ResolveInfo rij = results.get(j);
1829 if (rij.filter != null && rij.filter.hasAction(action)) {
1830 results.remove(j);
1831 if (Config.LOGV) Log.v(
1832 TAG, "Removing duplicate item from " + j
1833 + " due to action " + action + " at " + i);
1834 j--;
1835 N--;
1836 }
1837 }
1838 }
1839
1840 // If the caller didn't request filter information, drop it now
1841 // so we don't have to marshall/unmarshall it.
1842 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1843 rii.filter = null;
1844 }
1845 }
1846
1847 // Filter out the caller activity if so requested.
1848 if (caller != null) {
1849 N = results.size();
1850 for (int i=0; i<N; i++) {
1851 ActivityInfo ainfo = results.get(i).activityInfo;
1852 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1853 && caller.getClassName().equals(ainfo.name)) {
1854 results.remove(i);
1855 break;
1856 }
1857 }
1858 }
1859
1860 // If the caller didn't request filter information,
1861 // drop them now so we don't have to
1862 // marshall/unmarshall it.
1863 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1864 N = results.size();
1865 for (int i=0; i<N; i++) {
1866 results.get(i).filter = null;
1867 }
1868 }
1869
1870 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1871 return results;
1872 }
1873
1874 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1875 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001876 ComponentName comp = intent.getComponent();
1877 if (comp != null) {
1878 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1879 ActivityInfo ai = getReceiverInfo(comp, flags);
1880 if (ai != null) {
1881 ResolveInfo ri = new ResolveInfo();
1882 ri.activityInfo = ai;
1883 list.add(ri);
1884 }
1885 return list;
1886 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001889 String pkgName = intent.getPackage();
1890 if (pkgName == null) {
1891 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1892 resolvedType, flags);
1893 }
1894 PackageParser.Package pkg = mPackages.get(pkgName);
1895 if (pkg != null) {
1896 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1897 resolvedType, flags, pkg.receivers);
1898 }
1899 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 }
1901 }
1902
1903 public ResolveInfo resolveService(Intent intent, String resolvedType,
1904 int flags) {
1905 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1906 flags);
1907 if (query != null) {
1908 if (query.size() >= 1) {
1909 // If there is more than one service with the same priority,
1910 // just arbitrarily pick the first one.
1911 return query.get(0);
1912 }
1913 }
1914 return null;
1915 }
1916
1917 public List<ResolveInfo> queryIntentServices(Intent intent,
1918 String resolvedType, int flags) {
1919 ComponentName comp = intent.getComponent();
1920 if (comp != null) {
1921 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1922 ServiceInfo si = getServiceInfo(comp, flags);
1923 if (si != null) {
1924 ResolveInfo ri = new ResolveInfo();
1925 ri.serviceInfo = si;
1926 list.add(ri);
1927 }
1928 return list;
1929 }
1930
1931 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001932 String pkgName = intent.getPackage();
1933 if (pkgName == null) {
1934 return (List<ResolveInfo>)mServices.queryIntent(intent,
1935 resolvedType, flags);
1936 }
1937 PackageParser.Package pkg = mPackages.get(pkgName);
1938 if (pkg != null) {
1939 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1940 resolvedType, flags, pkg.services);
1941 }
1942 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 }
1944 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 public List<PackageInfo> getInstalledPackages(int flags) {
1947 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1948
1949 synchronized (mPackages) {
1950 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1951 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1952 while (i.hasNext()) {
1953 final PackageSetting ps = i.next();
1954 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1955 if(psPkg != null) {
1956 finalList.add(psPkg);
1957 }
1958 }
1959 }
1960 else {
1961 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1962 while (i.hasNext()) {
1963 final PackageParser.Package p = i.next();
1964 if (p.applicationInfo != null) {
1965 PackageInfo pi = generatePackageInfo(p, flags);
1966 if(pi != null) {
1967 finalList.add(pi);
1968 }
1969 }
1970 }
1971 }
1972 }
1973 return finalList;
1974 }
1975
1976 public List<ApplicationInfo> getInstalledApplications(int flags) {
1977 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1978 synchronized(mPackages) {
1979 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1980 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1981 while (i.hasNext()) {
1982 final PackageSetting ps = i.next();
1983 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1984 if(ai != null) {
1985 finalList.add(ai);
1986 }
1987 }
1988 }
1989 else {
1990 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1991 while (i.hasNext()) {
1992 final PackageParser.Package p = i.next();
1993 if (p.applicationInfo != null) {
1994 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1995 if(ai != null) {
1996 finalList.add(ai);
1997 }
1998 }
1999 }
2000 }
2001 }
2002 return finalList;
2003 }
2004
2005 public List<ApplicationInfo> getPersistentApplications(int flags) {
2006 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
2007
2008 synchronized (mPackages) {
2009 Iterator<PackageParser.Package> i = mPackages.values().iterator();
2010 while (i.hasNext()) {
2011 PackageParser.Package p = i.next();
2012 if (p.applicationInfo != null
2013 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
2014 && (!mSafeMode || (p.applicationInfo.flags
2015 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2016 finalList.add(p.applicationInfo);
2017 }
2018 }
2019 }
2020
2021 return finalList;
2022 }
2023
2024 public ProviderInfo resolveContentProvider(String name, int flags) {
2025 synchronized (mPackages) {
2026 final PackageParser.Provider provider = mProviders.get(name);
2027 return provider != null
2028 && mSettings.isEnabledLP(provider.info, flags)
2029 && (!mSafeMode || (provider.info.applicationInfo.flags
2030 &ApplicationInfo.FLAG_SYSTEM) != 0)
2031 ? PackageParser.generateProviderInfo(provider, flags)
2032 : null;
2033 }
2034 }
2035
Fred Quintana718d8a22009-04-29 17:53:20 -07002036 /**
2037 * @deprecated
2038 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 public void querySyncProviders(List outNames, List outInfo) {
2040 synchronized (mPackages) {
2041 Iterator<Map.Entry<String, PackageParser.Provider>> i
2042 = mProviders.entrySet().iterator();
2043
2044 while (i.hasNext()) {
2045 Map.Entry<String, PackageParser.Provider> entry = i.next();
2046 PackageParser.Provider p = entry.getValue();
2047
2048 if (p.syncable
2049 && (!mSafeMode || (p.info.applicationInfo.flags
2050 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2051 outNames.add(entry.getKey());
2052 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2053 }
2054 }
2055 }
2056 }
2057
2058 public List<ProviderInfo> queryContentProviders(String processName,
2059 int uid, int flags) {
2060 ArrayList<ProviderInfo> finalList = null;
2061
2062 synchronized (mPackages) {
2063 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2064 while (i.hasNext()) {
2065 PackageParser.Provider p = i.next();
2066 if (p.info.authority != null
2067 && (processName == null ||
2068 (p.info.processName.equals(processName)
2069 && p.info.applicationInfo.uid == uid))
2070 && mSettings.isEnabledLP(p.info, flags)
2071 && (!mSafeMode || (p.info.applicationInfo.flags
2072 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2073 if (finalList == null) {
2074 finalList = new ArrayList<ProviderInfo>(3);
2075 }
2076 finalList.add(PackageParser.generateProviderInfo(p,
2077 flags));
2078 }
2079 }
2080 }
2081
2082 if (finalList != null) {
2083 Collections.sort(finalList, mProviderInitOrderSorter);
2084 }
2085
2086 return finalList;
2087 }
2088
2089 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2090 int flags) {
2091 synchronized (mPackages) {
2092 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2093 return PackageParser.generateInstrumentationInfo(i, flags);
2094 }
2095 }
2096
2097 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2098 int flags) {
2099 ArrayList<InstrumentationInfo> finalList =
2100 new ArrayList<InstrumentationInfo>();
2101
2102 synchronized (mPackages) {
2103 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2104 while (i.hasNext()) {
2105 PackageParser.Instrumentation p = i.next();
2106 if (targetPackage == null
2107 || targetPackage.equals(p.info.targetPackage)) {
2108 finalList.add(PackageParser.generateInstrumentationInfo(p,
2109 flags));
2110 }
2111 }
2112 }
2113
2114 return finalList;
2115 }
2116
2117 private void scanDirLI(File dir, int flags, int scanMode) {
2118 Log.d(TAG, "Scanning app dir " + dir);
2119
2120 String[] files = dir.list();
2121
2122 int i;
2123 for (i=0; i<files.length; i++) {
2124 File file = new File(dir, files[i]);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002125 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002127 // Don't mess around with apps in system partition.
2128 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0) {
2129 // Delete the apk
2130 Log.w(TAG, "Cleaning up failed install of " + file);
2131 file.delete();
2132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 }
2134 }
2135
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002136 private static File getSettingsProblemFile() {
2137 File dataDir = Environment.getDataDirectory();
2138 File systemDir = new File(dataDir, "system");
2139 File fname = new File(systemDir, "uiderrors.txt");
2140 return fname;
2141 }
2142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 private static void reportSettingsProblem(int priority, String msg) {
2144 try {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002145 File fname = getSettingsProblemFile();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 FileOutputStream out = new FileOutputStream(fname, true);
2147 PrintWriter pw = new PrintWriter(out);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002148 SimpleDateFormat formatter = new SimpleDateFormat();
2149 String dateString = formatter.format(new Date(System.currentTimeMillis()));
2150 pw.println(dateString + ": " + msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 pw.close();
2152 FileUtils.setPermissions(
2153 fname.toString(),
2154 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2155 -1, -1);
2156 } catch (java.io.IOException e) {
2157 }
2158 Log.println(priority, TAG, msg);
2159 }
2160
2161 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2162 PackageParser.Package pkg, File srcFile, int parseFlags) {
2163 if (GET_CERTIFICATES) {
2164 if (ps == null || !ps.codePath.equals(srcFile)
2165 || ps.getTimeStamp() != srcFile.lastModified()) {
2166 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2167 if (!pp.collectCertificates(pkg, parseFlags)) {
2168 mLastScanError = pp.getParseError();
2169 return false;
2170 }
2171 }
2172 }
2173 return true;
2174 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 /*
2177 * Scan a package and return the newly parsed package.
2178 * Returns null in case of errors and the error code is stored in mLastScanError
2179 */
2180 private PackageParser.Package scanPackageLI(File scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002181 int parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 int scanMode) {
2183 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002184 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002186 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002189 scanPath,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002190 mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 if (pkg == null) {
2192 mLastScanError = pp.getParseError();
2193 return null;
2194 }
2195 PackageSetting ps;
2196 PackageSetting updatedPkg;
2197 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002198 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002199 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2200 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002201 // Verify certificates first
2202 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2203 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2204 return null;
2205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 if (updatedPkg != null) {
2207 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2208 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2209 }
2210 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2211 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002212 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2213 if (pkg.mVersionCode < ps.versionCode) {
2214 // The system package has been updated and the code path does not match
2215 // Ignore entry. Just return
2216 Log.w(TAG, "Package:" + pkg.packageName +
2217 " has been updated. Ignoring the one from path:"+scanFile);
2218 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2219 return null;
2220 } else {
2221 // Delete the older apk pointed to by ps
2222 // At this point, its safely assumed that package installation for
2223 // apps in system partition will go through. If not there won't be a working
2224 // version of the app
2225 synchronized (mPackages) {
2226 // Just remove the loaded entries from package lists.
2227 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002228 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002229 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2230 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002231 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 }
2234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 // The apk is forward locked (not public) if its code and resources
2236 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002237 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002239 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002240 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002241
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002242 String codePath = null;
2243 String resPath = null;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002244 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2245 if (ps != null && ps.resourcePathString != null) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002246 resPath = ps.resourcePathString;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002247 } else {
2248 // Should not happen at all. Just log an error.
2249 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2250 }
2251 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002252 resPath = pkg.mScanPath;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002253 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002254 codePath = pkg.mScanPath;
2255 // Set application objects path explicitly.
2256 setApplicationInfoPaths(pkg, codePath, resPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002258 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 }
2260
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002261 private static void setApplicationInfoPaths(PackageParser.Package pkg,
2262 String destCodePath, String destResPath) {
2263 pkg.mPath = pkg.mScanPath = destCodePath;
2264 pkg.applicationInfo.sourceDir = destCodePath;
2265 pkg.applicationInfo.publicSourceDir = destResPath;
2266 }
2267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 private static String fixProcessName(String defProcessName,
2269 String processName, int uid) {
2270 if (processName == null) {
2271 return defProcessName;
2272 }
2273 return processName;
2274 }
2275
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002276 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2278 if (pkg.mSignatures != null) {
2279 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2280 updateSignature)) {
2281 Log.e(TAG, "Package " + pkg.packageName
2282 + " signatures do not match the previously installed version; ignoring!");
2283 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2284 return false;
2285 }
2286
2287 if (pkgSetting.sharedUser != null) {
2288 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2289 pkg.mSignatures, updateSignature)) {
2290 Log.e(TAG, "Package " + pkg.packageName
2291 + " has no signatures that match those in shared user "
2292 + pkgSetting.sharedUser.name + "; ignoring!");
2293 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2294 return false;
2295 }
2296 }
2297 } else {
2298 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2299 }
2300 return true;
2301 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002302
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002303 public boolean performDexOpt(String packageName) {
2304 if (!mNoDexOpt) {
2305 return false;
2306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002307
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002308 PackageParser.Package p;
2309 synchronized (mPackages) {
2310 p = mPackages.get(packageName);
2311 if (p == null || p.mDidDexOpt) {
2312 return false;
2313 }
2314 }
2315 synchronized (mInstallLock) {
2316 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2317 }
2318 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002319
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002320 static final int DEX_OPT_SKIPPED = 0;
2321 static final int DEX_OPT_PERFORMED = 1;
2322 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002323
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002324 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2325 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002326 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002327 String path = pkg.mScanPath;
2328 int ret = 0;
2329 try {
2330 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002331 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002332 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002333 pkg.mDidDexOpt = true;
2334 performed = true;
2335 }
2336 } catch (FileNotFoundException e) {
2337 Log.w(TAG, "Apk not found for dexopt: " + path);
2338 ret = -1;
2339 } catch (IOException e) {
2340 Log.w(TAG, "Exception reading apk: " + path, e);
2341 ret = -1;
2342 }
2343 if (ret < 0) {
2344 //error from installer
2345 return DEX_OPT_FAILED;
2346 }
2347 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002348
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002349 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2350 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002351
2352 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2353 return Environment.isEncryptedFilesystemEnabled() &&
2354 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2355 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002356
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002357 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
2358 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
2359 Log.w(TAG, "Unable to update from " + oldPkg.name
2360 + " to " + newPkg.packageName
2361 + ": old package not in system partition");
2362 return false;
2363 } else if (mPackages.get(oldPkg.name) != null) {
2364 Log.w(TAG, "Unable to update from " + oldPkg.name
2365 + " to " + newPkg.packageName
2366 + ": old package still exists");
2367 return false;
2368 }
2369 return true;
2370 }
2371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 private PackageParser.Package scanPackageLI(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002373 PackageParser.Package pkg, int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002374 File scanFile = new File(pkg.mScanPath);
Suchi Amalapurapu7040ce72010-02-08 23:55:56 -08002375 if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
2376 pkg.applicationInfo.publicSourceDir == null) {
Suchi Amalapurapu08be55b2010-02-08 16:30:06 -08002377 // Bail out. The resource and code paths haven't been set.
2378 Log.w(TAG, " Code and resource paths haven't been set correctly");
2379 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
2380 return null;
2381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 mScanningPath = scanFile;
2383 if (pkg == null) {
2384 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2385 return null;
2386 }
2387
2388 final String pkgName = pkg.applicationInfo.packageName;
2389 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2390 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2391 }
2392
2393 if (pkgName.equals("android")) {
2394 synchronized (mPackages) {
2395 if (mAndroidApplication != null) {
2396 Log.w(TAG, "*************************************************");
2397 Log.w(TAG, "Core android package being redefined. Skipping.");
2398 Log.w(TAG, " file=" + mScanningPath);
2399 Log.w(TAG, "*************************************************");
2400 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2401 return null;
2402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002404 // Set up information for our fall-back user intent resolution
2405 // activity.
2406 mPlatformPackage = pkg;
2407 pkg.mVersionCode = mSdkVersion;
2408 mAndroidApplication = pkg.applicationInfo;
2409 mResolveActivity.applicationInfo = mAndroidApplication;
2410 mResolveActivity.name = ResolverActivity.class.getName();
2411 mResolveActivity.packageName = mAndroidApplication.packageName;
2412 mResolveActivity.processName = mAndroidApplication.processName;
2413 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2414 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2415 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2416 mResolveActivity.exported = true;
2417 mResolveActivity.enabled = true;
2418 mResolveInfo.activityInfo = mResolveActivity;
2419 mResolveInfo.priority = 0;
2420 mResolveInfo.preferredOrder = 0;
2421 mResolveInfo.match = 0;
2422 mResolveComponentName = new ComponentName(
2423 mAndroidApplication.packageName, mResolveActivity.name);
2424 }
2425 }
2426
2427 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2428 TAG, "Scanning package " + pkgName);
2429 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2430 Log.w(TAG, "*************************************************");
2431 Log.w(TAG, "Application package " + pkgName
2432 + " already installed. Skipping duplicate.");
2433 Log.w(TAG, "*************************************************");
2434 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2435 return null;
2436 }
2437
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002438 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002439 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2440 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 SharedUserSetting suid = null;
2443 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 synchronized (mPackages) {
2448 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002449 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2450 if (mTmpSharedLibraries == null ||
2451 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2452 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2453 }
2454 int num = 0;
2455 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2456 for (int i=0; i<N; i++) {
2457 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 if (file == null) {
2459 Log.e(TAG, "Package " + pkg.packageName
2460 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002461 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002462 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2463 return null;
2464 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002465 mTmpSharedLibraries[num] = file;
2466 num++;
2467 }
2468 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2469 for (int i=0; i<N; i++) {
2470 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2471 if (file == null) {
2472 Log.w(TAG, "Package " + pkg.packageName
2473 + " desires unavailable shared library "
2474 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2475 } else {
2476 mTmpSharedLibraries[num] = file;
2477 num++;
2478 }
2479 }
2480 if (num > 0) {
2481 pkg.usesLibraryFiles = new String[num];
2482 System.arraycopy(mTmpSharedLibraries, 0,
2483 pkg.usesLibraryFiles, 0, num);
2484 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002485
Dianne Hackborn49237342009-08-27 20:08:01 -07002486 if (pkg.reqFeatures != null) {
2487 N = pkg.reqFeatures.size();
2488 for (int i=0; i<N; i++) {
2489 FeatureInfo fi = pkg.reqFeatures.get(i);
2490 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2491 // Don't care.
2492 continue;
2493 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002494
Dianne Hackborn49237342009-08-27 20:08:01 -07002495 if (fi.name != null) {
2496 if (mAvailableFeatures.get(fi.name) == null) {
2497 Log.e(TAG, "Package " + pkg.packageName
2498 + " requires unavailable feature "
2499 + fi.name + "; failing!");
2500 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2501 return null;
2502 }
2503 }
2504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 }
2506 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 if (pkg.mSharedUserId != null) {
2509 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2510 pkg.applicationInfo.flags, true);
2511 if (suid == null) {
2512 Log.w(TAG, "Creating application package " + pkgName
2513 + " for shared user failed");
2514 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2515 return null;
2516 }
2517 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2518 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2519 + suid.userId + "): packages=" + suid.packages);
2520 }
2521 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002522
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002523 // Check if we are renaming from an original package name.
2524 PackageSetting origPackage = null;
2525 if (pkg.mOriginalPackage != null) {
2526 // We will only retrieve the setting for it if it already
2527 // exists; otherwise we need to make a new one later.
2528 origPackage = mSettings.peekPackageLP(pkg.mOriginalPackage);
2529 if (origPackage != null) {
2530 if (!verifyPackageUpdate(origPackage, pkg)) {
2531 origPackage = null;
2532 } else if (origPackage.sharedUser != null) {
2533 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
2534 Log.w(TAG, "Unable to migrate data from " + origPackage.name
2535 + " to " + pkg.packageName + ": old uid "
2536 + origPackage.sharedUser.name
2537 + " differs from " + pkg.mSharedUserId);
2538 origPackage = null;
2539 }
2540 } else {
2541 if (DEBUG_UPGRADE) Log.v(TAG, "Migrating data from "
2542 + origPackage.name + " to " + pkg.packageName);
2543 }
2544 }
2545 }
2546
2547 if (mTransferedPackages.contains(pkg.packageName)) {
2548 Log.w(TAG, "Package " + pkg.packageName
2549 + " was transferred to another, but its .apk remains");
2550 }
2551
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002552 // Just create the setting, don't add it yet. For already existing packages
2553 // the PkgSetting exists already and doesn't have to be created.
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002554 pkgSetting = mSettings.getPackageLP(pkg, origPackage, suid, destCodeFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 destResourceFile, pkg.applicationInfo.flags, true, false);
2556 if (pkgSetting == null) {
2557 Log.w(TAG, "Creating application package " + pkgName + " failed");
2558 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2559 return null;
2560 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002561 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 pkg.applicationInfo.uid = pkgSetting.userId;
2566 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002567
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002568 if (pkg.mAdoptPermissions != null) {
2569 // This package wants to adopt ownership of permissions from
2570 // another package.
2571 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
2572 String origName = pkg.mAdoptPermissions.get(i);
2573 PackageSetting orig = mSettings.peekPackageLP(origName);
2574 if (orig != null) {
2575 if (verifyPackageUpdate(orig, pkg)) {
2576 if (DEBUG_UPGRADE) Log.v(TAG, "Adopting permissions from "
2577 + origName + " to " + pkg.packageName);
2578 mSettings.transferPermissions(origName, pkg.packageName);
2579 }
2580 }
2581 }
2582 }
2583
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002584 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2586 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2587 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2588 return null;
2589 }
2590 // The signature has changed, but this package is in the system
2591 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002592 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 // However... if this package is part of a shared user, but it
2594 // doesn't match the signature of the shared user, let's fail.
2595 // What this means is that you can't change the signatures
2596 // associated with an overall shared user, which doesn't seem all
2597 // that unreasonable.
2598 if (pkgSetting.sharedUser != null) {
2599 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2600 pkg.mSignatures, false)) {
2601 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2602 return null;
2603 }
2604 }
2605 removeExisting = true;
2606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002607
The Android Open Source Project10592532009-03-18 17:39:46 -07002608 // Verify that this new package doesn't have any content providers
2609 // that conflict with existing packages. Only do this if the
2610 // package isn't already installed, since we don't want to break
2611 // things that are installed.
2612 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2613 int N = pkg.providers.size();
2614 int i;
2615 for (i=0; i<N; i++) {
2616 PackageParser.Provider p = pkg.providers.get(i);
2617 String names[] = p.info.authority.split(";");
2618 for (int j = 0; j < names.length; j++) {
2619 if (mProviders.containsKey(names[j])) {
2620 PackageParser.Provider other = mProviders.get(names[j]);
2621 Log.w(TAG, "Can't install because provider name " + names[j] +
2622 " (in package " + pkg.applicationInfo.packageName +
2623 ") is already used by "
2624 + ((other != null && other.component != null)
2625 ? other.component.getPackageName() : "?"));
2626 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2627 return null;
2628 }
2629 }
2630 }
2631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 }
2633
2634 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002635 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002637 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 if (ret != 0) {
2639 String msg = "System package " + pkg.packageName
2640 + " could not have data directory erased after signature change.";
2641 reportSettingsProblem(Log.WARN, msg);
2642 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2643 return null;
2644 }
2645 }
2646 Log.w(TAG, "System package " + pkg.packageName
2647 + " signature changed: existing data removed.");
2648 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2649 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 long scanFileTime = scanFile.lastModified();
2652 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2653 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2654 pkg.applicationInfo.processName = fixProcessName(
2655 pkg.applicationInfo.packageName,
2656 pkg.applicationInfo.processName,
2657 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658
2659 File dataPath;
2660 if (mPlatformPackage == pkg) {
2661 // The system package is special.
2662 dataPath = new File (Environment.getDataDirectory(), "system");
2663 pkg.applicationInfo.dataDir = dataPath.getPath();
2664 } else {
2665 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002666 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2667 if (useEncryptedFSDir) {
2668 dataPath = new File(mSecureAppDataDir, pkgName);
2669 } else {
2670 dataPath = new File(mAppDataDir, pkgName);
2671 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002672
2673 boolean uidError = false;
2674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002675 if (dataPath.exists()) {
2676 mOutPermissions[1] = 0;
2677 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2678 if (mOutPermissions[1] == pkg.applicationInfo.uid
2679 || !Process.supportsProcesses()) {
2680 pkg.applicationInfo.dataDir = dataPath.getPath();
2681 } else {
2682 boolean recovered = false;
2683 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2684 // If this is a system app, we can at least delete its
2685 // current data so the application will still work.
2686 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002687 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002688 if (ret >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002689 // Old data gone!
2690 String msg = "System package " + pkg.packageName
2691 + " has changed from uid: "
2692 + mOutPermissions[1] + " to "
2693 + pkg.applicationInfo.uid + "; old data erased";
2694 reportSettingsProblem(Log.WARN, msg);
2695 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002698 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002699 pkg.applicationInfo.uid);
2700 if (ret == -1) {
2701 // Ack should not happen!
2702 msg = "System package " + pkg.packageName
2703 + " could not have data directory re-created after delete.";
2704 reportSettingsProblem(Log.WARN, msg);
2705 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2706 return null;
2707 }
2708 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002710 if (!recovered) {
2711 mHasSystemUidErrors = true;
2712 }
2713 }
2714 if (!recovered) {
2715 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2716 + pkg.applicationInfo.uid + "/fs_"
2717 + mOutPermissions[1];
2718 String msg = "Package " + pkg.packageName
2719 + " has mismatched uid: "
2720 + mOutPermissions[1] + " on disk, "
2721 + pkg.applicationInfo.uid + " in settings";
2722 synchronized (mPackages) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002723 mSettings.mReadMessages.append(msg);
2724 mSettings.mReadMessages.append('\n');
2725 uidError = true;
2726 if (!pkgSetting.uidError) {
2727 reportSettingsProblem(Log.ERROR, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002729 }
2730 }
2731 }
2732 pkg.applicationInfo.dataDir = dataPath.getPath();
2733 } else {
2734 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2735 Log.v(TAG, "Want this data dir: " + dataPath);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002736 if (pkgSetting.origPackage != null) {
2737 synchronized (mPackages) {
2738 // This package is being update from another; rename the
2739 // old one's data dir.
2740 String msg = "Transfering data from old package "
2741 + pkgSetting.origPackage.name + " to new package "
2742 + pkgSetting.name;
2743 reportSettingsProblem(Log.WARN, msg);
2744 if (mInstaller != null) {
2745 int ret = mInstaller.rename(pkgSetting.origPackage.name,
2746 pkgName, useEncryptedFSDir);
2747 if(ret < 0) {
2748 msg = "Error transfering data from old package "
2749 + pkgSetting.origPackage.name + " to new package "
2750 + pkgSetting.name;
2751 reportSettingsProblem(Log.WARN, msg);
2752 }
Makoto Onukia7d7f792010-02-09 13:16:02 -08002753 // And now uninstall the old package.
2754 mInstaller.remove(pkgSetting.origPackage.name, useEncryptedFSDir);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002755 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002756 mSettings.removePackageLP(pkgSetting.origPackage.name);
2757 }
2758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002759 //invoke installer to do the actual installation
2760 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002761 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 pkg.applicationInfo.uid);
2763 if(ret < 0) {
2764 // Error from installer
2765 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2766 return null;
2767 }
2768 } else {
2769 dataPath.mkdirs();
2770 if (dataPath.exists()) {
2771 FileUtils.setPermissions(
2772 dataPath.toString(),
2773 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2774 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2775 }
2776 }
2777 if (dataPath.exists()) {
2778 pkg.applicationInfo.dataDir = dataPath.getPath();
2779 } else {
2780 Log.w(TAG, "Unable to create data directory: " + dataPath);
2781 pkg.applicationInfo.dataDir = null;
2782 }
2783 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002784
2785 pkgSetting.uidError = uidError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
2787
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08002788 // No longer need to retain this.
2789 if (pkgSetting.origPackage != null) {
2790 mTransferedPackages.add(pkgSetting.origPackage.name);
2791 pkgSetting.origPackage = null;
2792 }
2793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002794 // Perform shared library installation and dex validation and
2795 // optimization, if this is not a system app.
2796 if (mInstaller != null) {
2797 String path = scanFile.getPath();
2798 if (scanFileNewer) {
2799 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002800 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2801 if (err != PackageManager.INSTALL_SUCCEEDED) {
2802 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 return null;
2804 }
2805 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002806 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002807
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002808 if ((scanMode&SCAN_NO_DEX) == 0) {
2809 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002810 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2811 return null;
2812 }
2813 }
2814 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 if (mFactoryTest && pkg.requestedPermissions.contains(
2817 android.Manifest.permission.FACTORY_TEST)) {
2818 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2819 }
2820
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002821 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 if ((scanMode&SCAN_MONITOR) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 mAppDirs.put(pkg.mPath, pkg);
2824 }
2825
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002826 // Request the ActivityManager to kill the process(only for existing packages)
2827 // so that we do not end up in a confused state while the user is still using the older
2828 // version of the application while the new one gets installed.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002829 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0) {
2830 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002831 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002832 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002834 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002836 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002838 mPackages.put(pkg.applicationInfo.packageName, pkg);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08002839 // Make sure we don't accidentally delete its data.
2840 mSettings.mPackagesToBeCleaned.remove(pkgName);
2841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002842 int N = pkg.providers.size();
2843 StringBuilder r = null;
2844 int i;
2845 for (i=0; i<N; i++) {
2846 PackageParser.Provider p = pkg.providers.get(i);
2847 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2848 p.info.processName, pkg.applicationInfo.uid);
2849 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2850 p.info.name), p);
2851 p.syncable = p.info.isSyncable;
2852 String names[] = p.info.authority.split(";");
2853 p.info.authority = null;
2854 for (int j = 0; j < names.length; j++) {
2855 if (j == 1 && p.syncable) {
2856 // We only want the first authority for a provider to possibly be
2857 // syncable, so if we already added this provider using a different
2858 // authority clear the syncable flag. We copy the provider before
2859 // changing it because the mProviders object contains a reference
2860 // to a provider that we don't want to change.
2861 // Only do this for the second authority since the resulting provider
2862 // object can be the same for all future authorities for this provider.
2863 p = new PackageParser.Provider(p);
2864 p.syncable = false;
2865 }
2866 if (!mProviders.containsKey(names[j])) {
2867 mProviders.put(names[j], p);
2868 if (p.info.authority == null) {
2869 p.info.authority = names[j];
2870 } else {
2871 p.info.authority = p.info.authority + ";" + names[j];
2872 }
2873 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2874 Log.d(TAG, "Registered content provider: " + names[j] +
2875 ", className = " + p.info.name +
2876 ", isSyncable = " + p.info.isSyncable);
2877 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002878 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 Log.w(TAG, "Skipping provider name " + names[j] +
2880 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002881 "): name already used by "
2882 + ((other != null && other.component != null)
2883 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 }
2885 }
2886 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2887 if (r == null) {
2888 r = new StringBuilder(256);
2889 } else {
2890 r.append(' ');
2891 }
2892 r.append(p.info.name);
2893 }
2894 }
2895 if (r != null) {
2896 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002899 N = pkg.services.size();
2900 r = null;
2901 for (i=0; i<N; i++) {
2902 PackageParser.Service s = pkg.services.get(i);
2903 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2904 s.info.processName, pkg.applicationInfo.uid);
2905 mServices.addService(s);
2906 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2907 if (r == null) {
2908 r = new StringBuilder(256);
2909 } else {
2910 r.append(' ');
2911 }
2912 r.append(s.info.name);
2913 }
2914 }
2915 if (r != null) {
2916 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2917 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002919 N = pkg.receivers.size();
2920 r = null;
2921 for (i=0; i<N; i++) {
2922 PackageParser.Activity a = pkg.receivers.get(i);
2923 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2924 a.info.processName, pkg.applicationInfo.uid);
2925 mReceivers.addActivity(a, "receiver");
2926 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2927 if (r == null) {
2928 r = new StringBuilder(256);
2929 } else {
2930 r.append(' ');
2931 }
2932 r.append(a.info.name);
2933 }
2934 }
2935 if (r != null) {
2936 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2937 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 N = pkg.activities.size();
2940 r = null;
2941 for (i=0; i<N; i++) {
2942 PackageParser.Activity a = pkg.activities.get(i);
2943 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2944 a.info.processName, pkg.applicationInfo.uid);
2945 mActivities.addActivity(a, "activity");
2946 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2947 if (r == null) {
2948 r = new StringBuilder(256);
2949 } else {
2950 r.append(' ');
2951 }
2952 r.append(a.info.name);
2953 }
2954 }
2955 if (r != null) {
2956 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2957 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959 N = pkg.permissionGroups.size();
2960 r = null;
2961 for (i=0; i<N; i++) {
2962 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2963 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2964 if (cur == null) {
2965 mPermissionGroups.put(pg.info.name, pg);
2966 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2967 if (r == null) {
2968 r = new StringBuilder(256);
2969 } else {
2970 r.append(' ');
2971 }
2972 r.append(pg.info.name);
2973 }
2974 } else {
2975 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2976 + pg.info.packageName + " ignored: original from "
2977 + cur.info.packageName);
2978 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2979 if (r == null) {
2980 r = new StringBuilder(256);
2981 } else {
2982 r.append(' ');
2983 }
2984 r.append("DUP:");
2985 r.append(pg.info.name);
2986 }
2987 }
2988 }
2989 if (r != null) {
2990 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2991 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 N = pkg.permissions.size();
2994 r = null;
2995 for (i=0; i<N; i++) {
2996 PackageParser.Permission p = pkg.permissions.get(i);
2997 HashMap<String, BasePermission> permissionMap =
2998 p.tree ? mSettings.mPermissionTrees
2999 : mSettings.mPermissions;
3000 p.group = mPermissionGroups.get(p.info.group);
3001 if (p.info.group == null || p.group != null) {
3002 BasePermission bp = permissionMap.get(p.info.name);
3003 if (bp == null) {
3004 bp = new BasePermission(p.info.name, p.info.packageName,
3005 BasePermission.TYPE_NORMAL);
3006 permissionMap.put(p.info.name, bp);
3007 }
3008 if (bp.perm == null) {
3009 if (bp.sourcePackage == null
3010 || bp.sourcePackage.equals(p.info.packageName)) {
3011 BasePermission tree = findPermissionTreeLP(p.info.name);
3012 if (tree == null
3013 || tree.sourcePackage.equals(p.info.packageName)) {
3014 bp.perm = p;
3015 bp.uid = pkg.applicationInfo.uid;
3016 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3017 if (r == null) {
3018 r = new StringBuilder(256);
3019 } else {
3020 r.append(' ');
3021 }
3022 r.append(p.info.name);
3023 }
3024 } else {
3025 Log.w(TAG, "Permission " + p.info.name + " from package "
3026 + p.info.packageName + " ignored: base tree "
3027 + tree.name + " is from package "
3028 + tree.sourcePackage);
3029 }
3030 } else {
3031 Log.w(TAG, "Permission " + p.info.name + " from package "
3032 + p.info.packageName + " ignored: original from "
3033 + bp.sourcePackage);
3034 }
3035 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3036 if (r == null) {
3037 r = new StringBuilder(256);
3038 } else {
3039 r.append(' ');
3040 }
3041 r.append("DUP:");
3042 r.append(p.info.name);
3043 }
3044 } else {
3045 Log.w(TAG, "Permission " + p.info.name + " from package "
3046 + p.info.packageName + " ignored: no group "
3047 + p.group);
3048 }
3049 }
3050 if (r != null) {
3051 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3052 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 N = pkg.instrumentation.size();
3055 r = null;
3056 for (i=0; i<N; i++) {
3057 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3058 a.info.packageName = pkg.applicationInfo.packageName;
3059 a.info.sourceDir = pkg.applicationInfo.sourceDir;
3060 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
3061 a.info.dataDir = pkg.applicationInfo.dataDir;
3062 mInstrumentation.put(a.component, a);
3063 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
3064 if (r == null) {
3065 r = new StringBuilder(256);
3066 } else {
3067 r.append(' ');
3068 }
3069 r.append(a.info.name);
3070 }
3071 }
3072 if (r != null) {
3073 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3074 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003075
Dianne Hackborn854060af2009-07-09 18:14:31 -07003076 if (pkg.protectedBroadcasts != null) {
3077 N = pkg.protectedBroadcasts.size();
3078 for (i=0; i<N; i++) {
3079 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
3080 }
3081 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 pkgSetting.setTimeStamp(scanFileTime);
3084 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 return pkg;
3087 }
3088
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003089 private void killApplication(String pkgName, int uid) {
3090 // Request the ActivityManager to kill the process(only for existing packages)
3091 // so that we do not end up in a confused state while the user is still using the older
3092 // version of the application while the new one gets installed.
3093 IActivityManager am = ActivityManagerNative.getDefault();
3094 if (am != null) {
3095 try {
3096 am.killApplicationWithUid(pkgName, uid);
3097 } catch (RemoteException e) {
3098 }
3099 }
3100 }
3101
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003102 // The following constants are returned by cachePackageSharedLibsForAbiLI
3103 // to indicate if native shared libraries were found in the package.
3104 // Values are:
3105 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
3106 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
3107 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
3108 // in package (and not installed)
3109 //
3110 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
3111 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
3112 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003114 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
3115 // and automatically copy them to /data/data/<appname>/lib if present.
3116 //
3117 // NOTE: this method may throw an IOException if the library cannot
3118 // be copied to its final destination, e.g. if there isn't enough
3119 // room left on the data partition, or a ZipException if the package
3120 // file is malformed.
3121 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003122 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
3123 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003124 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
3125 final String apkLib = "lib/";
3126 final int apkLibLen = apkLib.length();
3127 final int cpuAbiLen = cpuAbi.length();
3128 final String libPrefix = "lib";
3129 final int libPrefixLen = libPrefix.length();
3130 final String libSuffix = ".so";
3131 final int libSuffixLen = libSuffix.length();
3132 boolean hasNativeLibraries = false;
3133 boolean installedNativeLibraries = false;
3134
3135 // the minimum length of a valid native shared library of the form
3136 // lib/<something>/lib<name>.so.
3137 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
3138
3139 ZipFile zipFile = new ZipFile(scanFile);
3140 Enumeration<ZipEntry> entries =
3141 (Enumeration<ZipEntry>) zipFile.entries();
3142
3143 while (entries.hasMoreElements()) {
3144 ZipEntry entry = entries.nextElement();
3145 // skip directories
3146 if (entry.isDirectory()) {
3147 continue;
3148 }
3149 String entryName = entry.getName();
3150
3151 // check that the entry looks like lib/<something>/lib<name>.so
3152 // here, but don't check the ABI just yet.
3153 //
3154 // - must be sufficiently long
3155 // - must end with libSuffix, i.e. ".so"
3156 // - must start with apkLib, i.e. "lib/"
3157 if (entryName.length() < minEntryLen ||
3158 !entryName.endsWith(libSuffix) ||
3159 !entryName.startsWith(apkLib) ) {
3160 continue;
3161 }
3162
3163 // file name must start with libPrefix, i.e. "lib"
3164 int lastSlash = entryName.lastIndexOf('/');
3165
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003166 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003167 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
3168 continue;
3169 }
3170
3171 hasNativeLibraries = true;
3172
3173 // check the cpuAbi now, between lib/ and /lib<name>.so
3174 //
3175 if (lastSlash != apkLibLen + cpuAbiLen ||
3176 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3177 continue;
3178
3179 // extract the library file name, ensure it doesn't contain
3180 // weird characters. we're guaranteed here that it doesn't contain
3181 // a directory separator though.
3182 String libFileName = entryName.substring(lastSlash+1);
3183 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3184 continue;
3185 }
3186
3187 installedNativeLibraries = true;
3188
3189 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3190 File.separator + libFileName;
3191 File sharedLibraryFile = new File(sharedLibraryFilePath);
3192 if (! sharedLibraryFile.exists() ||
3193 sharedLibraryFile.length() != entry.getSize() ||
3194 sharedLibraryFile.lastModified() != entry.getTime()) {
3195 if (Config.LOGD) {
3196 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003198 if (mInstaller == null) {
3199 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003200 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003201 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003202 sharedLibraryFile);
3203 }
3204 }
3205 if (!hasNativeLibraries)
3206 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3207
3208 if (!installedNativeLibraries)
3209 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3210
3211 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3212 }
3213
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003214 // Find the gdbserver executable program in a package at
3215 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3216 //
3217 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3218 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3219 //
3220 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3221 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3222 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3223 final String GDBSERVER = "gdbserver";
3224 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3225
3226 ZipFile zipFile = new ZipFile(scanFile);
3227 Enumeration<ZipEntry> entries =
3228 (Enumeration<ZipEntry>) zipFile.entries();
3229
3230 while (entries.hasMoreElements()) {
3231 ZipEntry entry = entries.nextElement();
3232 // skip directories
3233 if (entry.isDirectory()) {
3234 continue;
3235 }
3236 String entryName = entry.getName();
3237
3238 if (!entryName.equals(apkGdbServerPath)) {
3239 continue;
3240 }
3241
3242 String installGdbServerPath = installGdbServerDir.getPath() +
3243 "/" + GDBSERVER;
3244 File installGdbServerFile = new File(installGdbServerPath);
3245 if (! installGdbServerFile.exists() ||
3246 installGdbServerFile.length() != entry.getSize() ||
3247 installGdbServerFile.lastModified() != entry.getTime()) {
3248 if (Config.LOGD) {
3249 Log.d(TAG, "Caching gdbserver " + entry.getName());
3250 }
3251 if (mInstaller == null) {
3252 installGdbServerDir.mkdir();
3253 }
3254 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3255 installGdbServerFile);
3256 }
3257 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3258 }
3259 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3260 }
3261
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003262 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3263 // and copy them to /data/data/<appname>/lib.
3264 //
3265 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3266 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3267 // one if ro.product.cpu.abi2 is defined.
3268 //
3269 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3270 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003271 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003272 try {
3273 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3274
3275 // some architectures are capable of supporting several CPU ABIs
3276 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3277 // this is indicated by the definition of the ro.product.cpu.abi2
3278 // system property.
3279 //
3280 // only scan the package twice in case of ABI mismatch
3281 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003282 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003283 if (cpuAbi2 != null) {
3284 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003286
3287 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3288 Log.w(TAG,"Native ABI mismatch from package file");
3289 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003291
3292 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3293 cpuAbi = cpuAbi2;
3294 }
3295 }
3296
3297 // for debuggable packages, also extract gdbserver from lib/<abi>
3298 // into /data/data/<appname>/lib too.
3299 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3300 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3301 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3302 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3303 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3304 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003306 } catch (ZipException e) {
3307 Log.w(TAG, "Failed to extract data from package file", e);
3308 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003310 Log.w(TAG, "Failed to cache package shared libs", e);
3311 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003313 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 }
3315
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003316 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003318 File binaryDir,
3319 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 InputStream inputStream = zipFile.getInputStream(entry);
3321 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003322 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003324 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 // now need to be left as world readable and owned by the system.
3326 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3327 ! tempFile.setLastModified(entry.getTime()) ||
3328 FileUtils.setPermissions(tempFilePath,
3329 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003330 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003332 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003333 // Failed to properly write file.
3334 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003335 throw new IOException("Couldn't create cached binary "
3336 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003337 }
3338 } finally {
3339 inputStream.close();
3340 }
3341 }
3342
3343 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3344 if (chatty && Config.LOGD) Log.d(
3345 TAG, "Removing package " + pkg.applicationInfo.packageName );
3346
3347 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 mPackages.remove(pkg.applicationInfo.packageName);
3351 if (pkg.mPath != null) {
3352 mAppDirs.remove(pkg.mPath);
3353 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 PackageSetting ps = (PackageSetting)pkg.mExtras;
3356 if (ps != null && ps.sharedUser != null) {
3357 // XXX don't do this until the data is removed.
3358 if (false) {
3359 ps.sharedUser.packages.remove(ps);
3360 if (ps.sharedUser.packages.size() == 0) {
3361 // Remove.
3362 }
3363 }
3364 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 int N = pkg.providers.size();
3367 StringBuilder r = null;
3368 int i;
3369 for (i=0; i<N; i++) {
3370 PackageParser.Provider p = pkg.providers.get(i);
3371 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3372 p.info.name));
3373 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 /* The is another ContentProvider with this authority when
3376 * this app was installed so this authority is null,
3377 * Ignore it as we don't have to unregister the provider.
3378 */
3379 continue;
3380 }
3381 String names[] = p.info.authority.split(";");
3382 for (int j = 0; j < names.length; j++) {
3383 if (mProviders.get(names[j]) == p) {
3384 mProviders.remove(names[j]);
3385 if (chatty && Config.LOGD) Log.d(
3386 TAG, "Unregistered content provider: " + names[j] +
3387 ", className = " + p.info.name +
3388 ", isSyncable = " + p.info.isSyncable);
3389 }
3390 }
3391 if (chatty) {
3392 if (r == null) {
3393 r = new StringBuilder(256);
3394 } else {
3395 r.append(' ');
3396 }
3397 r.append(p.info.name);
3398 }
3399 }
3400 if (r != null) {
3401 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 N = pkg.services.size();
3405 r = null;
3406 for (i=0; i<N; i++) {
3407 PackageParser.Service s = pkg.services.get(i);
3408 mServices.removeService(s);
3409 if (chatty) {
3410 if (r == null) {
3411 r = new StringBuilder(256);
3412 } else {
3413 r.append(' ');
3414 }
3415 r.append(s.info.name);
3416 }
3417 }
3418 if (r != null) {
3419 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3420 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 N = pkg.receivers.size();
3423 r = null;
3424 for (i=0; i<N; i++) {
3425 PackageParser.Activity a = pkg.receivers.get(i);
3426 mReceivers.removeActivity(a, "receiver");
3427 if (chatty) {
3428 if (r == null) {
3429 r = new StringBuilder(256);
3430 } else {
3431 r.append(' ');
3432 }
3433 r.append(a.info.name);
3434 }
3435 }
3436 if (r != null) {
3437 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3438 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 N = pkg.activities.size();
3441 r = null;
3442 for (i=0; i<N; i++) {
3443 PackageParser.Activity a = pkg.activities.get(i);
3444 mActivities.removeActivity(a, "activity");
3445 if (chatty) {
3446 if (r == null) {
3447 r = new StringBuilder(256);
3448 } else {
3449 r.append(' ');
3450 }
3451 r.append(a.info.name);
3452 }
3453 }
3454 if (r != null) {
3455 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3456 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 N = pkg.permissions.size();
3459 r = null;
3460 for (i=0; i<N; i++) {
3461 PackageParser.Permission p = pkg.permissions.get(i);
3462 boolean tree = false;
3463 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3464 if (bp == null) {
3465 tree = true;
3466 bp = mSettings.mPermissionTrees.get(p.info.name);
3467 }
3468 if (bp != null && bp.perm == p) {
3469 if (bp.type != BasePermission.TYPE_BUILTIN) {
3470 if (tree) {
3471 mSettings.mPermissionTrees.remove(p.info.name);
3472 } else {
3473 mSettings.mPermissions.remove(p.info.name);
3474 }
3475 } else {
3476 bp.perm = null;
3477 }
3478 if (chatty) {
3479 if (r == null) {
3480 r = new StringBuilder(256);
3481 } else {
3482 r.append(' ');
3483 }
3484 r.append(p.info.name);
3485 }
3486 }
3487 }
3488 if (r != null) {
3489 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3490 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003492 N = pkg.instrumentation.size();
3493 r = null;
3494 for (i=0; i<N; i++) {
3495 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3496 mInstrumentation.remove(a.component);
3497 if (chatty) {
3498 if (r == null) {
3499 r = new StringBuilder(256);
3500 } else {
3501 r.append(' ');
3502 }
3503 r.append(a.info.name);
3504 }
3505 }
3506 if (r != null) {
3507 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3508 }
3509 }
3510 }
3511
3512 private static final boolean isPackageFilename(String name) {
3513 return name != null && name.endsWith(".apk");
3514 }
3515
3516 private void updatePermissionsLP() {
3517 // Make sure there are no dangling permission trees.
3518 Iterator<BasePermission> it = mSettings.mPermissionTrees
3519 .values().iterator();
3520 while (it.hasNext()) {
3521 BasePermission bp = it.next();
3522 if (bp.perm == null) {
3523 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3524 + " from package " + bp.sourcePackage);
3525 it.remove();
3526 }
3527 }
3528
3529 // Make sure all dynamic permissions have been assigned to a package,
3530 // and make sure there are no dangling permissions.
3531 it = mSettings.mPermissions.values().iterator();
3532 while (it.hasNext()) {
3533 BasePermission bp = it.next();
3534 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3535 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3536 + bp.name + " pkg=" + bp.sourcePackage
3537 + " info=" + bp.pendingInfo);
3538 if (bp.perm == null && bp.pendingInfo != null) {
3539 BasePermission tree = findPermissionTreeLP(bp.name);
3540 if (tree != null) {
3541 bp.perm = new PackageParser.Permission(tree.perm.owner,
3542 new PermissionInfo(bp.pendingInfo));
3543 bp.perm.info.packageName = tree.perm.info.packageName;
3544 bp.perm.info.name = bp.name;
3545 bp.uid = tree.uid;
3546 }
3547 }
3548 }
3549 if (bp.perm == null) {
3550 Log.w(TAG, "Removing dangling permission: " + bp.name
3551 + " from package " + bp.sourcePackage);
3552 it.remove();
3553 }
3554 }
3555
3556 // Now update the permissions for all packages, in particular
3557 // replace the granted permissions of the system packages.
3558 for (PackageParser.Package pkg : mPackages.values()) {
3559 grantPermissionsLP(pkg, false);
3560 }
3561 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003563 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3564 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3565 if (ps == null) {
3566 return;
3567 }
3568 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3569 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 if (replace) {
3572 ps.permissionsFixed = false;
3573 if (gp == ps) {
3574 gp.grantedPermissions.clear();
3575 gp.gids = mGlobalGids;
3576 }
3577 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003579 if (gp.gids == null) {
3580 gp.gids = mGlobalGids;
3581 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 final int N = pkg.requestedPermissions.size();
3584 for (int i=0; i<N; i++) {
3585 String name = pkg.requestedPermissions.get(i);
3586 BasePermission bp = mSettings.mPermissions.get(name);
3587 PackageParser.Permission p = bp != null ? bp.perm : null;
3588 if (false) {
3589 if (gp != ps) {
3590 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3591 + ": " + p);
3592 }
3593 }
3594 if (p != null) {
3595 final String perm = p.info.name;
3596 boolean allowed;
3597 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3598 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3599 allowed = true;
3600 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3601 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003602 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003603 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003604 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003605 == PackageManager.SIGNATURE_MATCH);
3606 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3607 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3608 // For updated system applications, the signatureOrSystem permission
3609 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003610 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003611 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3612 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3613 if(sysPs.grantedPermissions.contains(perm)) {
3614 allowed = true;
3615 } else {
3616 allowed = false;
3617 }
3618 } else {
3619 allowed = true;
3620 }
3621 }
3622 }
3623 } else {
3624 allowed = false;
3625 }
3626 if (false) {
3627 if (gp != ps) {
3628 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3629 }
3630 }
3631 if (allowed) {
3632 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3633 && ps.permissionsFixed) {
3634 // If this is an existing, non-system package, then
3635 // we can't add any new permissions to it.
3636 if (!gp.loadedPermissions.contains(perm)) {
3637 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003638 // Except... if this is a permission that was added
3639 // to the platform (note: need to only do this when
3640 // updating the platform).
3641 final int NP = PackageParser.NEW_PERMISSIONS.length;
3642 for (int ip=0; ip<NP; ip++) {
3643 final PackageParser.NewPermissionInfo npi
3644 = PackageParser.NEW_PERMISSIONS[ip];
3645 if (npi.name.equals(perm)
3646 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3647 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003648 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003649 + pkg.packageName);
3650 break;
3651 }
3652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 }
3654 }
3655 if (allowed) {
3656 if (!gp.grantedPermissions.contains(perm)) {
3657 addedPermission = true;
3658 gp.grantedPermissions.add(perm);
3659 gp.gids = appendInts(gp.gids, bp.gids);
3660 }
3661 } else {
3662 Log.w(TAG, "Not granting permission " + perm
3663 + " to package " + pkg.packageName
3664 + " because it was previously installed without");
3665 }
3666 } else {
3667 Log.w(TAG, "Not granting permission " + perm
3668 + " to package " + pkg.packageName
3669 + " (protectionLevel=" + p.info.protectionLevel
3670 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3671 + ")");
3672 }
3673 } else {
3674 Log.w(TAG, "Unknown permission " + name
3675 + " in package " + pkg.packageName);
3676 }
3677 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003680 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3681 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 // This is the first that we have heard about this package, so the
3683 // permissions we have now selected are fixed until explicitly
3684 // changed.
3685 ps.permissionsFixed = true;
3686 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3687 }
3688 }
3689
3690 private final class ActivityIntentResolver
3691 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003692 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003693 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003694 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 }
3696
Mihai Preda074edef2009-05-18 17:13:31 +02003697 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003699 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3701 }
3702
Mihai Predaeae850c2009-05-13 10:13:48 +02003703 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3704 ArrayList<PackageParser.Activity> packageActivities) {
3705 if (packageActivities == null) {
3706 return null;
3707 }
3708 mFlags = flags;
3709 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3710 int N = packageActivities.size();
3711 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3712 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003713
3714 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003715 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003716 intentFilters = packageActivities.get(i).intents;
3717 if (intentFilters != null && intentFilters.size() > 0) {
3718 listCut.add(intentFilters);
3719 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003720 }
3721 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3722 }
3723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 public final void addActivity(PackageParser.Activity a, String type) {
3725 mActivities.put(a.component, a);
3726 if (SHOW_INFO || Config.LOGV) Log.v(
3727 TAG, " " + type + " " +
3728 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3729 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3730 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003731 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003732 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3733 if (SHOW_INFO || Config.LOGV) {
3734 Log.v(TAG, " IntentFilter:");
3735 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3736 }
3737 if (!intent.debugCheck()) {
3738 Log.w(TAG, "==> For Activity " + a.info.name);
3739 }
3740 addFilter(intent);
3741 }
3742 }
3743
3744 public final void removeActivity(PackageParser.Activity a, String type) {
3745 mActivities.remove(a.component);
3746 if (SHOW_INFO || Config.LOGV) Log.v(
3747 TAG, " " + type + " " +
3748 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3749 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3750 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003751 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003752 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3753 if (SHOW_INFO || Config.LOGV) {
3754 Log.v(TAG, " IntentFilter:");
3755 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3756 }
3757 removeFilter(intent);
3758 }
3759 }
3760
3761 @Override
3762 protected boolean allowFilterResult(
3763 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3764 ActivityInfo filterAi = filter.activity.info;
3765 for (int i=dest.size()-1; i>=0; i--) {
3766 ActivityInfo destAi = dest.get(i).activityInfo;
3767 if (destAi.name == filterAi.name
3768 && destAi.packageName == filterAi.packageName) {
3769 return false;
3770 }
3771 }
3772 return true;
3773 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 @Override
3776 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3777 int match) {
3778 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3779 return null;
3780 }
3781 final PackageParser.Activity activity = info.activity;
3782 if (mSafeMode && (activity.info.applicationInfo.flags
3783 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3784 return null;
3785 }
3786 final ResolveInfo res = new ResolveInfo();
3787 res.activityInfo = PackageParser.generateActivityInfo(activity,
3788 mFlags);
3789 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3790 res.filter = info;
3791 }
3792 res.priority = info.getPriority();
3793 res.preferredOrder = activity.owner.mPreferredOrder;
3794 //System.out.println("Result: " + res.activityInfo.className +
3795 // " = " + res.priority);
3796 res.match = match;
3797 res.isDefault = info.hasDefault;
3798 res.labelRes = info.labelRes;
3799 res.nonLocalizedLabel = info.nonLocalizedLabel;
3800 res.icon = info.icon;
3801 return res;
3802 }
3803
3804 @Override
3805 protected void sortResults(List<ResolveInfo> results) {
3806 Collections.sort(results, mResolvePrioritySorter);
3807 }
3808
3809 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003810 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003811 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003812 out.print(prefix); out.print(
3813 Integer.toHexString(System.identityHashCode(filter.activity)));
3814 out.print(' ');
3815 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003816 }
3817
3818// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3819// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3820// final List<ResolveInfo> retList = Lists.newArrayList();
3821// while (i.hasNext()) {
3822// final ResolveInfo resolveInfo = i.next();
3823// if (isEnabledLP(resolveInfo.activityInfo)) {
3824// retList.add(resolveInfo);
3825// }
3826// }
3827// return retList;
3828// }
3829
3830 // Keys are String (activity class name), values are Activity.
3831 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3832 = new HashMap<ComponentName, PackageParser.Activity>();
3833 private int mFlags;
3834 }
3835
3836 private final class ServiceIntentResolver
3837 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003838 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003840 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 }
3842
Mihai Preda074edef2009-05-18 17:13:31 +02003843 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003845 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3847 }
3848
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003849 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3850 ArrayList<PackageParser.Service> packageServices) {
3851 if (packageServices == null) {
3852 return null;
3853 }
3854 mFlags = flags;
3855 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3856 int N = packageServices.size();
3857 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3858 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3859
3860 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3861 for (int i = 0; i < N; ++i) {
3862 intentFilters = packageServices.get(i).intents;
3863 if (intentFilters != null && intentFilters.size() > 0) {
3864 listCut.add(intentFilters);
3865 }
3866 }
3867 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3868 }
3869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 public final void addService(PackageParser.Service s) {
3871 mServices.put(s.component, s);
3872 if (SHOW_INFO || Config.LOGV) Log.v(
3873 TAG, " " + (s.info.nonLocalizedLabel != null
3874 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3875 if (SHOW_INFO || Config.LOGV) Log.v(
3876 TAG, " Class=" + s.info.name);
3877 int NI = s.intents.size();
3878 int j;
3879 for (j=0; j<NI; j++) {
3880 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3881 if (SHOW_INFO || Config.LOGV) {
3882 Log.v(TAG, " IntentFilter:");
3883 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3884 }
3885 if (!intent.debugCheck()) {
3886 Log.w(TAG, "==> For Service " + s.info.name);
3887 }
3888 addFilter(intent);
3889 }
3890 }
3891
3892 public final void removeService(PackageParser.Service s) {
3893 mServices.remove(s.component);
3894 if (SHOW_INFO || Config.LOGV) Log.v(
3895 TAG, " " + (s.info.nonLocalizedLabel != null
3896 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3897 if (SHOW_INFO || Config.LOGV) Log.v(
3898 TAG, " Class=" + s.info.name);
3899 int NI = s.intents.size();
3900 int j;
3901 for (j=0; j<NI; j++) {
3902 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3903 if (SHOW_INFO || Config.LOGV) {
3904 Log.v(TAG, " IntentFilter:");
3905 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3906 }
3907 removeFilter(intent);
3908 }
3909 }
3910
3911 @Override
3912 protected boolean allowFilterResult(
3913 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3914 ServiceInfo filterSi = filter.service.info;
3915 for (int i=dest.size()-1; i>=0; i--) {
3916 ServiceInfo destAi = dest.get(i).serviceInfo;
3917 if (destAi.name == filterSi.name
3918 && destAi.packageName == filterSi.packageName) {
3919 return false;
3920 }
3921 }
3922 return true;
3923 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 @Override
3926 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3927 int match) {
3928 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3929 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3930 return null;
3931 }
3932 final PackageParser.Service service = info.service;
3933 if (mSafeMode && (service.info.applicationInfo.flags
3934 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3935 return null;
3936 }
3937 final ResolveInfo res = new ResolveInfo();
3938 res.serviceInfo = PackageParser.generateServiceInfo(service,
3939 mFlags);
3940 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3941 res.filter = filter;
3942 }
3943 res.priority = info.getPriority();
3944 res.preferredOrder = service.owner.mPreferredOrder;
3945 //System.out.println("Result: " + res.activityInfo.className +
3946 // " = " + res.priority);
3947 res.match = match;
3948 res.isDefault = info.hasDefault;
3949 res.labelRes = info.labelRes;
3950 res.nonLocalizedLabel = info.nonLocalizedLabel;
3951 res.icon = info.icon;
3952 return res;
3953 }
3954
3955 @Override
3956 protected void sortResults(List<ResolveInfo> results) {
3957 Collections.sort(results, mResolvePrioritySorter);
3958 }
3959
3960 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003961 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003963 out.print(prefix); out.print(
3964 Integer.toHexString(System.identityHashCode(filter.service)));
3965 out.print(' ');
3966 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 }
3968
3969// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3970// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3971// final List<ResolveInfo> retList = Lists.newArrayList();
3972// while (i.hasNext()) {
3973// final ResolveInfo resolveInfo = (ResolveInfo) i;
3974// if (isEnabledLP(resolveInfo.serviceInfo)) {
3975// retList.add(resolveInfo);
3976// }
3977// }
3978// return retList;
3979// }
3980
3981 // Keys are String (activity class name), values are Activity.
3982 private final HashMap<ComponentName, PackageParser.Service> mServices
3983 = new HashMap<ComponentName, PackageParser.Service>();
3984 private int mFlags;
3985 };
3986
3987 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3988 new Comparator<ResolveInfo>() {
3989 public int compare(ResolveInfo r1, ResolveInfo r2) {
3990 int v1 = r1.priority;
3991 int v2 = r2.priority;
3992 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3993 if (v1 != v2) {
3994 return (v1 > v2) ? -1 : 1;
3995 }
3996 v1 = r1.preferredOrder;
3997 v2 = r2.preferredOrder;
3998 if (v1 != v2) {
3999 return (v1 > v2) ? -1 : 1;
4000 }
4001 if (r1.isDefault != r2.isDefault) {
4002 return r1.isDefault ? -1 : 1;
4003 }
4004 v1 = r1.match;
4005 v2 = r2.match;
4006 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
4007 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4008 }
4009 };
4010
4011 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
4012 new Comparator<ProviderInfo>() {
4013 public int compare(ProviderInfo p1, ProviderInfo p2) {
4014 final int v1 = p1.initOrder;
4015 final int v2 = p2.initOrder;
4016 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
4017 }
4018 };
4019
4020 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
4021 IActivityManager am = ActivityManagerNative.getDefault();
4022 if (am != null) {
4023 try {
4024 final Intent intent = new Intent(action,
4025 pkg != null ? Uri.fromParts("package", pkg, null) : null);
4026 if (extras != null) {
4027 intent.putExtras(extras);
4028 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07004029 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 am.broadcastIntent(
4031 null, intent,
4032 null, null, 0, null, null, null, false, false);
4033 } catch (RemoteException ex) {
4034 }
4035 }
4036 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004037
4038 public String nextPackageToClean(String lastPackage) {
4039 synchronized (mPackages) {
4040 if (!mMediaMounted) {
4041 // If the external storage is no longer mounted at this point,
4042 // the caller may not have been able to delete all of this
4043 // packages files and can not delete any more. Bail.
4044 return null;
4045 }
4046 if (lastPackage != null) {
4047 mSettings.mPackagesToBeCleaned.remove(lastPackage);
4048 }
4049 return mSettings.mPackagesToBeCleaned.size() > 0
4050 ? mSettings.mPackagesToBeCleaned.get(0) : null;
4051 }
4052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053
Dianne Hackborne83cefce2010-02-04 17:38:14 -08004054 void schedulePackageCleaning(String packageName) {
4055 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName));
4056 }
4057
4058 void startCleaningPackages() {
4059 synchronized (mPackages) {
4060 if (!mMediaMounted) {
4061 return;
4062 }
4063 if (mSettings.mPackagesToBeCleaned.size() <= 0) {
4064 return;
4065 }
4066 }
4067 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE);
4068 intent.setComponent(DEFAULT_CONTAINER_COMPONENT);
4069 IActivityManager am = ActivityManagerNative.getDefault();
4070 if (am != null) {
4071 try {
4072 am.startService(null, intent, null);
4073 } catch (RemoteException e) {
4074 }
4075 }
4076 }
4077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 private final class AppDirObserver extends FileObserver {
4079 public AppDirObserver(String path, int mask, boolean isrom) {
4080 super(path, mask);
4081 mRootDir = path;
4082 mIsRom = isrom;
4083 }
4084
4085 public void onEvent(int event, String path) {
4086 String removedPackage = null;
4087 int removedUid = -1;
4088 String addedPackage = null;
4089 int addedUid = -1;
4090
4091 synchronized (mInstallLock) {
4092 String fullPathStr = null;
4093 File fullPath = null;
4094 if (path != null) {
4095 fullPath = new File(mRootDir, path);
4096 fullPathStr = fullPath.getPath();
4097 }
4098
4099 if (Config.LOGV) Log.v(
4100 TAG, "File " + fullPathStr + " changed: "
4101 + Integer.toHexString(event));
4102
4103 if (!isPackageFilename(path)) {
4104 if (Config.LOGV) Log.v(
4105 TAG, "Ignoring change of non-package file: " + fullPathStr);
4106 return;
4107 }
4108
4109 if ((event&REMOVE_EVENTS) != 0) {
4110 synchronized (mInstallLock) {
4111 PackageParser.Package p = mAppDirs.get(fullPathStr);
4112 if (p != null) {
4113 removePackageLI(p, true);
4114 removedPackage = p.applicationInfo.packageName;
4115 removedUid = p.applicationInfo.uid;
4116 }
4117 }
4118 }
4119
4120 if ((event&ADD_EVENTS) != 0) {
4121 PackageParser.Package p = mAppDirs.get(fullPathStr);
4122 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004123 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
4125 PackageParser.PARSE_CHATTY |
4126 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08004127 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 if (p != null) {
4129 synchronized (mPackages) {
4130 grantPermissionsLP(p, false);
4131 }
4132 addedPackage = p.applicationInfo.packageName;
4133 addedUid = p.applicationInfo.uid;
4134 }
4135 }
4136 }
4137
4138 synchronized (mPackages) {
4139 mSettings.writeLP();
4140 }
4141 }
4142
4143 if (removedPackage != null) {
4144 Bundle extras = new Bundle(1);
4145 extras.putInt(Intent.EXTRA_UID, removedUid);
4146 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
4147 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4148 }
4149 if (addedPackage != null) {
4150 Bundle extras = new Bundle(1);
4151 extras.putInt(Intent.EXTRA_UID, addedUid);
4152 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
4153 }
4154 }
4155
4156 private final String mRootDir;
4157 private final boolean mIsRom;
4158 }
Jacek Surazski65e13172009-04-28 15:26:38 +02004159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004160 /* Called when a downloaded package installation has been confirmed by the user */
4161 public void installPackage(
4162 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02004163 installPackage(packageURI, observer, flags, null);
4164 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004165
Jacek Surazski65e13172009-04-28 15:26:38 +02004166 /* Called when a downloaded package installation has been confirmed by the user */
4167 public void installPackage(
4168 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
4169 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 mContext.enforceCallingOrSelfPermission(
4171 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004172
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004173 Message msg = mHandler.obtainMessage(INIT_COPY);
4174 msg.obj = createInstallArgs(packageURI, observer, flags, installerPackageName);
4175 mHandler.sendMessage(msg);
4176 }
4177
4178 private InstallArgs createInstallArgs(Uri packageURI, IPackageInstallObserver observer,
4179 int flags, String installerPackageName) {
4180 if (installOnSd(flags)) {
4181 return new SdInstallArgs(packageURI, observer, flags,
4182 installerPackageName);
4183 } else {
4184 return new FileInstallArgs(packageURI, observer, flags,
4185 installerPackageName);
4186 }
4187 }
4188
4189 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
4190 if (installOnSd(flags)) {
4191 return new SdInstallArgs(fullCodePath, fullResourcePath);
4192 } else {
4193 return new FileInstallArgs(fullCodePath, fullResourcePath);
4194 }
4195 }
4196
4197 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 // Queue up an async operation since the package installation may take a little while.
4199 mHandler.post(new Runnable() {
4200 public void run() {
4201 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004202 // Result object to be returned
4203 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004204 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004205 res.uid = -1;
4206 res.pkg = null;
4207 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004208 args.doPreInstall(res.returnCode);
4209 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004210 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004211 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004212 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004213 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004215 if (args.observer != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004216 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004217 args.observer.packageInstalled(res.name, res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 } catch (RemoteException e) {
4219 Log.i(TAG, "Observer no longer exists.");
4220 }
4221 }
4222 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
4223 // call appears in the synchronized block above.
4224 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4225 res.removedInfo.sendBroadcast(false, true);
4226 Bundle extras = new Bundle(1);
4227 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004228 final boolean update = res.removedInfo.removedPackage != null;
4229 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4231 }
4232 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
4233 res.pkg.applicationInfo.packageName,
4234 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004235 if (update) {
4236 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
4237 res.pkg.applicationInfo.packageName,
4238 extras);
4239 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004240 if (res.removedInfo.args != null) {
4241 // Remove the replaced package's older resources safely now
4242 synchronized (mInstallLock) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004243 res.removedInfo.args.doPostDeleteLI(true);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004244 }
4245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246 }
4247 Runtime.getRuntime().gc();
4248 }
4249 });
4250 }
4251
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004252 static abstract class InstallArgs {
4253 final IPackageInstallObserver observer;
4254 final int flags;
4255 final Uri packageURI;
4256 final String installerPackageName;
4257
4258 InstallArgs(Uri packageURI,
4259 IPackageInstallObserver observer, int flags,
4260 String installerPackageName) {
4261 this.packageURI = packageURI;
4262 this.flags = flags;
4263 this.observer = observer;
4264 this.installerPackageName = installerPackageName;
4265 }
4266
4267 abstract void createCopyFile();
4268 abstract int copyApk(IMediaContainerService imcs);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004269 abstract int doPreInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004270 abstract boolean doRename(int status, String pkgName, String oldCodePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004271 abstract int doPostInstall(int status);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004272 abstract String getCodePath();
4273 abstract String getResourcePath();
4274 // Need installer lock especially for dex file removal.
4275 abstract void cleanUpResourcesLI();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004276 abstract boolean doPostDeleteLI(boolean delete);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004277 }
4278
4279 class FileInstallArgs extends InstallArgs {
4280 File installDir;
4281 String codeFileName;
4282 String resourceFileName;
4283
4284 FileInstallArgs(Uri packageURI,
4285 IPackageInstallObserver observer, int flags,
4286 String installerPackageName) {
4287 super(packageURI, observer, flags, installerPackageName);
4288 }
4289
4290 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4291 super(null, null, 0, null);
4292 File codeFile = new File(fullCodePath);
4293 installDir = codeFile.getParentFile();
4294 codeFileName = fullCodePath;
4295 resourceFileName = fullResourcePath;
4296 }
4297
4298 void createCopyFile() {
4299 boolean fwdLocked = isFwdLocked(flags);
4300 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4301 codeFileName = createTempPackageFile(installDir).getPath();
4302 resourceFileName = getResourcePathFromCodePath();
4303 }
4304
4305 String getCodePath() {
4306 return codeFileName;
4307 }
4308
4309 int copyApk(IMediaContainerService imcs) {
4310 // Get a ParcelFileDescriptor to write to the output file
4311 File codeFile = new File(codeFileName);
4312 ParcelFileDescriptor out = null;
4313 try {
4314 out = ParcelFileDescriptor.open(codeFile,
4315 ParcelFileDescriptor.MODE_READ_WRITE);
4316 } catch (FileNotFoundException e) {
4317 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4318 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4319 }
4320 // Copy the resource now
4321 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4322 try {
4323 if (imcs.copyResource(packageURI, out)) {
4324 ret = PackageManager.INSTALL_SUCCEEDED;
4325 }
4326 } catch (RemoteException e) {
4327 } finally {
4328 try { if (out != null) out.close(); } catch (IOException e) {}
4329 }
4330 return ret;
4331 }
4332
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004333 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004334 if (status != PackageManager.INSTALL_SUCCEEDED) {
4335 cleanUp();
4336 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004337 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004338 }
4339
4340 boolean doRename(int status, final String pkgName, String oldCodePath) {
4341 if (status != PackageManager.INSTALL_SUCCEEDED) {
4342 cleanUp();
4343 return false;
4344 } else {
4345 // Rename based on packageName
4346 File codeFile = new File(getCodePath());
4347 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4348 File desFile = new File(installDir, apkName + ".apk");
4349 if (!codeFile.renameTo(desFile)) {
4350 return false;
4351 }
4352 // Reset paths since the file has been renamed.
4353 codeFileName = desFile.getPath();
4354 resourceFileName = getResourcePathFromCodePath();
4355 // Set permissions
4356 if (!setPermissions(pkgName)) {
4357 // Failed setting permissions.
4358 return false;
4359 }
4360 return true;
4361 }
4362 }
4363
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004364 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004365 if (status != PackageManager.INSTALL_SUCCEEDED) {
4366 cleanUp();
4367 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004368 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004369 }
4370
4371 String getResourcePath() {
4372 return resourceFileName;
4373 }
4374
4375 String getResourcePathFromCodePath() {
4376 String codePath = getCodePath();
4377 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4378 String apkNameOnly = getApkName(codePath);
4379 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4380 } else {
4381 return codePath;
4382 }
4383 }
4384
4385 private boolean cleanUp() {
4386 boolean ret = true;
4387 String sourceDir = getCodePath();
4388 String publicSourceDir = getResourcePath();
4389 if (sourceDir != null) {
4390 File sourceFile = new File(sourceDir);
4391 if (!sourceFile.exists()) {
4392 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4393 ret = false;
4394 }
4395 // Delete application's code and resources
4396 sourceFile.delete();
4397 }
4398 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4399 final File publicSourceFile = new File(publicSourceDir);
4400 if (!publicSourceFile.exists()) {
4401 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4402 }
4403 if (publicSourceFile.exists()) {
4404 publicSourceFile.delete();
4405 }
4406 }
4407 return ret;
4408 }
4409
4410 void cleanUpResourcesLI() {
4411 String sourceDir = getCodePath();
4412 if (cleanUp() && mInstaller != null) {
4413 int retCode = mInstaller.rmdex(sourceDir);
4414 if (retCode < 0) {
4415 Log.w(TAG, "Couldn't remove dex file for package: "
4416 + " at location "
4417 + sourceDir + ", retcode=" + retCode);
4418 // we don't consider this to be a failure of the core package deletion
4419 }
4420 }
4421 }
4422
4423 private boolean setPermissions(String pkgName) {
4424 // TODO Do this in a more elegant way later on. for now just a hack
4425 if (!isFwdLocked(flags)) {
4426 final int filePermissions =
4427 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4428 |FileUtils.S_IROTH;
4429 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4430 if (retCode != 0) {
4431 Log.e(TAG, "Couldn't set new package file permissions for " +
4432 getCodePath()
4433 + ". The return code was: " + retCode);
4434 // TODO Define new internal error
4435 return false;
4436 }
4437 return true;
4438 }
4439 return true;
4440 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004441
4442 boolean doPostDeleteLI(boolean delete) {
4443 cleanUpResourcesLI();
4444 return true;
4445 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004446 }
4447
4448 class SdInstallArgs extends InstallArgs {
4449 String cid;
4450 String cachePath;
4451 static final String RES_FILE_NAME = "pkg.apk";
4452
4453 SdInstallArgs(Uri packageURI,
4454 IPackageInstallObserver observer, int flags,
4455 String installerPackageName) {
4456 super(packageURI, observer, flags, installerPackageName);
4457 }
4458
4459 SdInstallArgs(String fullCodePath, String fullResourcePath) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004460 super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004461 // Extract cid from fullCodePath
4462 int eidx = fullCodePath.lastIndexOf("/");
4463 String subStr1 = fullCodePath.substring(0, eidx);
4464 int sidx = subStr1.lastIndexOf("/");
4465 cid = subStr1.substring(sidx+1, eidx);
4466 cachePath = subStr1;
4467 }
4468
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004469 SdInstallArgs(String cid) {
4470 super(null, null, ApplicationInfo.FLAG_ON_SDCARD, null);
4471 this.cid = cid;
4472 }
4473
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004474 void createCopyFile() {
4475 cid = getTempContainerId();
4476 }
4477
4478 int copyApk(IMediaContainerService imcs) {
4479 try {
4480 cachePath = imcs.copyResourceToContainer(
4481 packageURI, cid,
4482 getEncryptKey(), RES_FILE_NAME);
4483 } catch (RemoteException e) {
4484 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004485 return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
4486 PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004487 }
4488
4489 @Override
4490 String getCodePath() {
4491 return cachePath + "/" + RES_FILE_NAME;
4492 }
4493
4494 @Override
4495 String getResourcePath() {
4496 return cachePath + "/" + RES_FILE_NAME;
4497 }
4498
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004499 int doPreInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004500 if (status != PackageManager.INSTALL_SUCCEEDED) {
4501 // Destroy container
4502 destroySdDir(cid);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004503 } else {
4504 // STOPSHIP Remove once new api is added in MountService
4505 //boolean mounted = isContainerMounted(cid);
4506 boolean mounted = false;
4507 if (!mounted) {
4508 cachePath = mountSdDir(cid, Process.SYSTEM_UID);
4509 if (cachePath == null) {
4510 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4511 }
4512 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004513 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004514 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004515 }
4516
4517 boolean doRename(int status, final String pkgName,
4518 String oldCodePath) {
4519 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004520 String newCachePath = null;
4521 /*final int RENAME_FAILED = 1;
4522 final int MOUNT_FAILED = 2;
4523 final int DESTROY_FAILED = 3;
4524 final int PASS = 4;
4525 int errCode = RENAME_FAILED;
4526 if (mounted) {
4527 // Unmount the container
4528 if (!unMountSdDir(cid)) {
4529 Log.i(TAG, "Failed to unmount " + cid + " before renaming");
4530 return false;
4531 }
4532 mounted = false;
4533 }
4534 if (renameSdDir(cid, newCacheId)) {
4535 errCode = MOUNT_FAILED;
4536 if ((newCachePath = mountSdDir(newCacheId, Process.SYSTEM_UID)) != null) {
4537 errCode = PASS;
4538 }
4539 }
4540 String errMsg = "";
4541 switch (errCode) {
4542 case RENAME_FAILED:
4543 errMsg = "RENAME_FAILED";
4544 break;
4545 case MOUNT_FAILED:
4546 errMsg = "MOUNT_FAILED";
4547 break;
4548 case DESTROY_FAILED:
4549 errMsg = "DESTROY_FAILED";
4550 break;
4551 default:
4552 errMsg = "PASS";
4553 break;
4554 }
4555 Log.i(TAG, "Status: " + errMsg);
4556 if (errCode != PASS) {
4557 return false;
4558 }
4559 Log.i(TAG, "Succesfully renamed " + cid + " to " +newCacheId +
4560 " at path: " + cachePath + " to new path: " + newCachePath);
4561 cid = newCacheId;
4562 cachePath = newCachePath;
4563 return true;
4564 */
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004565 // STOPSHIP TEMPORARY HACK FOR RENAME
4566 // Create new container at newCachePath
4567 String codePath = getCodePath();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004568 final int CREATE_FAILED = 1;
4569 final int COPY_FAILED = 3;
4570 final int FINALIZE_FAILED = 5;
4571 final int PASS = 7;
4572 int errCode = CREATE_FAILED;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004573
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004574 if ((newCachePath = createSdDir(new File(codePath), newCacheId)) != null) {
4575 errCode = COPY_FAILED;
4576 // Copy file from codePath
4577 if (FileUtils.copyFile(new File(codePath), new File(newCachePath, RES_FILE_NAME))) {
4578 errCode = FINALIZE_FAILED;
4579 if (finalizeSdDir(newCacheId)) {
4580 errCode = PASS;
4581 }
4582 }
4583 }
4584 // Print error based on errCode
4585 String errMsg = "";
4586 switch (errCode) {
4587 case CREATE_FAILED:
4588 errMsg = "CREATE_FAILED";
4589 break;
4590 case COPY_FAILED:
4591 errMsg = "COPY_FAILED";
4592 destroySdDir(newCacheId);
4593 break;
4594 case FINALIZE_FAILED:
4595 errMsg = "FINALIZE_FAILED";
4596 destroySdDir(newCacheId);
4597 break;
4598 default:
4599 errMsg = "PASS";
4600 break;
4601 }
4602 // Destroy the temporary container
4603 destroySdDir(cid);
4604 Log.i(TAG, "Status: " + errMsg);
4605 if (errCode != PASS) {
4606 return false;
4607 }
4608 cid = newCacheId;
4609 cachePath = newCachePath;
4610
4611 return true;
4612 }
4613
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004614 int doPostInstall(int status) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004615 if (status != PackageManager.INSTALL_SUCCEEDED) {
4616 cleanUp();
4617 } else {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004618 // STOP SHIP Change this once new api is added.
4619 //boolean mounted = isContainerMounted(cid);
4620 boolean mounted = false;
4621 if (!mounted) {
4622 mountSdDir(cid, Process.SYSTEM_UID);
4623 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004624 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004625 return status;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004626 }
4627
4628 private void cleanUp() {
4629 // Destroy secure container
4630 destroySdDir(cid);
4631 }
4632
4633 void cleanUpResourcesLI() {
4634 String sourceFile = getCodePath();
4635 // Remove dex file
4636 if (mInstaller != null) {
4637 int retCode = mInstaller.rmdex(sourceFile.toString());
4638 if (retCode < 0) {
4639 Log.w(TAG, "Couldn't remove dex file for package: "
4640 + " at location "
4641 + sourceFile.toString() + ", retcode=" + retCode);
4642 // we don't consider this to be a failure of the core package deletion
4643 }
4644 }
4645 cleanUp();
4646 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004647
4648 boolean matchContainer(String app) {
4649 if (cid.startsWith(app)) {
4650 return true;
4651 }
4652 return false;
4653 }
4654
4655 String getPackageName() {
4656 int idx = cid.lastIndexOf("-");
4657 if (idx == -1) {
4658 return cid;
4659 }
4660 return cid.substring(0, idx);
4661 }
4662
4663 boolean doPostDeleteLI(boolean delete) {
4664 boolean ret = false;
4665 boolean mounted = isContainerMounted(cid);
4666 if (mounted) {
4667 // Unmount first
4668 ret = unMountSdDir(cid);
4669 }
4670 if (ret && delete) {
4671 cleanUpResourcesLI();
4672 }
4673 return ret;
4674 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004675 };
4676
4677 // Utility method used to create code paths based on package name and available index.
4678 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
4679 String idxStr = "";
4680 int idx = 1;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004681 // Fall back to default value of idx=1 if prefix is not
4682 // part of oldCodePath
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004683 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004684 String subStr = oldCodePath;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004685 // Drop the suffix right away
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004686 if (subStr.endsWith(suffix)) {
4687 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004688 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004689 // If oldCodePath already contains prefix find out the
4690 // ending index to either increment or decrement.
4691 int sidx = subStr.lastIndexOf(prefix);
4692 if (sidx != -1) {
4693 subStr = subStr.substring(sidx + prefix.length());
4694 if (subStr != null) {
4695 if (subStr.startsWith("-")) {
4696 subStr = subStr.substring(1);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004697 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08004698 try {
4699 idx = Integer.parseInt(subStr);
4700 if (idx <= 1) {
4701 idx++;
4702 } else {
4703 idx--;
4704 }
4705 } catch(NumberFormatException e) {
4706 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004707 }
4708 }
4709 }
4710 idxStr = "-" + Integer.toString(idx);
4711 return prefix + idxStr;
4712 }
4713
4714 // Utility method that returns the relative package path with respect
4715 // to the installation directory. Like say for /data/data/com.test-1.apk
4716 // string com.test-1 is returned.
4717 static String getApkName(String codePath) {
4718 if (codePath == null) {
4719 return null;
4720 }
4721 int sidx = codePath.lastIndexOf("/");
4722 int eidx = codePath.lastIndexOf(".");
4723 if (eidx == -1) {
4724 eidx = codePath.length();
4725 } else if (eidx == 0) {
4726 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
4727 return null;
4728 }
4729 return codePath.substring(sidx+1, eidx);
4730 }
4731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 class PackageInstalledInfo {
4733 String name;
4734 int uid;
4735 PackageParser.Package pkg;
4736 int returnCode;
4737 PackageRemovedInfo removedInfo;
4738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 /*
4741 * Install a non-existing package.
4742 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004743 private void installNewPackageLI(PackageParser.Package pkg,
4744 int parseFlags,
4745 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004746 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08004748 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004749 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08004750
4751 if (useEncryptedFilesystemForPackage(pkg)) {
4752 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
4753 } else {
4754 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
4755 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 res.name = pkgName;
4757 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004758 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004760 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 + " without first uninstalling.");
4762 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4763 return;
4764 }
4765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004767 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004769 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4771 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4772 }
4773 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004774 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004775 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 res);
4777 // delete the partially installed application. the data directory will have to be
4778 // restored if it was already existing
4779 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4780 // remove package from internal structures. Note that we want deletePackageX to
4781 // delete the package data and cache directories that it created in
4782 // scanPackageLocked, unless those directories existed before we even tried to
4783 // install.
4784 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004785 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
4787 res.removedInfo);
4788 }
4789 }
4790 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004791
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004792 private void replacePackageLI(PackageParser.Package pkg,
4793 int parseFlags,
4794 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004795 String installerPackageName, PackageInstalledInfo res) {
4796
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004797 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004798 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 // First find the old package info and check signatures
4800 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004801 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004802 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
4803 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004804 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4805 return;
4806 }
4807 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004808 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 if(sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004810 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004812 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 }
4814 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004817 PackageParser.Package pkg,
4818 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004819 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 PackageParser.Package newPackage = null;
4821 String pkgName = deletedPackage.packageName;
4822 boolean deletedPkg = true;
4823 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004824
Jacek Surazski65e13172009-04-28 15:26:38 +02004825 String oldInstallerPackageName = null;
4826 synchronized (mPackages) {
4827 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
4828 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004829
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004830 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004831 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004832 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 res.removedInfo)) {
4834 // If the existing package was'nt successfully deleted
4835 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4836 deletedPkg = false;
4837 } else {
4838 // Successfully deleted the old package. Now proceed with re-installation
4839 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004840 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004842 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004843 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4844 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08004845 }
4846 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004847 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004848 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004849 res);
4850 updatedSettings = true;
4851 }
4852 }
4853
4854 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4855 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004856 // were keeping around in case we needed them (see below) can now be deleted.
4857 // This info will be set on the res.removedInfo to clean up later on as post
4858 // install action.
4859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 //update signature on the new package setting
4861 //this should always succeed, since we checked the
4862 //signature earlier.
4863 synchronized(mPackages) {
4864 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4865 parseFlags, true);
4866 }
4867 } else {
4868 // remove package from internal structures. Note that we want deletePackageX to
4869 // delete the package data and cache directories that it created in
4870 // scanPackageLocked, unless those directories existed before we even tried to
4871 // install.
4872 if(updatedSettings) {
4873 deletePackageLI(
4874 pkgName, true,
4875 PackageManager.DONT_DELETE_DATA,
4876 res.removedInfo);
4877 }
4878 // Since we failed to install the new package we need to restore the old
4879 // package that we deleted.
4880 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004881 File restoreFile = new File(deletedPackage.mPath);
4882 if (restoreFile == null) {
4883 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4884 return;
4885 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004886 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4887 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004888 // Parse old package
4889 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
4890 scanPackageLI(restoreFile, parseFlags, scanMode);
4891 synchronized (mPackages) {
4892 grantPermissionsLP(deletedPackage, false);
4893 mSettings.writeLP();
4894 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004895 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4896 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 }
4899 }
4900 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004902 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004903 PackageParser.Package pkg,
4904 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004905 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 PackageParser.Package newPackage = null;
4907 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004908 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 PackageParser.PARSE_IS_SYSTEM;
4910 String packageName = deletedPackage.packageName;
4911 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4912 if (packageName == null) {
4913 Log.w(TAG, "Attempt to delete null packageName.");
4914 return;
4915 }
4916 PackageParser.Package oldPkg;
4917 PackageSetting oldPkgSetting;
4918 synchronized (mPackages) {
4919 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004920 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004921 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4922 (oldPkgSetting == null)) {
4923 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4924 return;
4925 }
4926 }
4927 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4928 res.removedInfo.removedPackage = packageName;
4929 // Remove existing system package
4930 removePackageLI(oldPkg, true);
4931 synchronized (mPackages) {
4932 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4933 }
4934
4935 // Successfully disabled the old package. Now proceed with re-installation
4936 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4937 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004938 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004940 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004941 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4942 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4943 }
4944 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004945 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946 updatedSettings = true;
4947 }
4948
4949 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4950 //update signature on the new package setting
4951 //this should always succeed, since we checked the
4952 //signature earlier.
4953 synchronized(mPackages) {
4954 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4955 parseFlags, true);
4956 }
4957 } else {
4958 // Re installation failed. Restore old information
4959 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004960 if (newPackage != null) {
4961 removePackageLI(newPackage, true);
4962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004964 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004966 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 // Restore the old system information in Settings
4968 synchronized(mPackages) {
4969 if(updatedSettings) {
4970 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004971 mSettings.setInstallerPackageName(packageName,
4972 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004973 }
4974 mSettings.writeLP();
4975 }
4976 }
4977 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004978
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004979 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004980 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004981 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 synchronized (mPackages) {
4983 //write settings. the installStatus will be incomplete at this stage.
4984 //note that the new package setting would have already been
4985 //added to mPackages. It hasn't been persisted yet.
4986 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4987 mSettings.writeLP();
4988 }
4989
4990 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004991 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4992 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004994 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4996 return;
4997 }
4998 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004999 res.returnCode = setPermissionsLI(newPackage);
5000 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5001 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005003 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 }
5005 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
5006 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005007 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005008 }
5009 }
5010
5011 synchronized (mPackages) {
5012 grantPermissionsLP(newPackage, true);
5013 res.name = pkgName;
5014 res.uid = newPackage.applicationInfo.uid;
5015 res.pkg = newPackage;
5016 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02005017 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5019 //to update install status
5020 mSettings.writeLP();
5021 }
5022 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005023
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005024 private void installPackageLI(InstallArgs args,
5025 boolean newInstall, PackageInstalledInfo res) {
5026 int pFlags = args.flags;
5027 String installerPackageName = args.installerPackageName;
5028 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005029 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
5030 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005031 boolean replace = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005032 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
5033 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07005034 // Result object to be returned
5035 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
5036
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005037 // Retrieve PackageSettings and parse package
5038 int parseFlags = PackageParser.PARSE_CHATTY |
5039 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
5040 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
5041 parseFlags |= mDefParseFlags;
5042 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
5043 pp.setSeparateProcesses(mSeparateProcesses);
5044 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
5045 null, mMetrics, parseFlags);
5046 if (pkg == null) {
5047 res.returnCode = pp.getParseError();
5048 return;
5049 }
5050 String pkgName = res.name = pkg.packageName;
5051 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
5052 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
5053 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
5054 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005056 }
5057 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
5058 res.returnCode = pp.getParseError();
5059 return;
5060 }
5061 // Some preinstall checks
5062 if (forwardLocked && onSd) {
5063 // Make sure forward locked apps can only be installed
5064 // on internal storage
5065 Log.w(TAG, "Cannot install protected apps on sdcard");
5066 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5067 return;
5068 }
5069 // Get rid of all references to package scan path via parser.
5070 pp = null;
5071 String oldCodePath = null;
5072 boolean systemApp = false;
5073 synchronized (mPackages) {
5074 // Check if installing already existing package
5075 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
5076 && mPackages.containsKey(pkgName)) {
5077 replace = true;
5078 }
5079 PackageSetting ps = mSettings.mPackages.get(pkgName);
5080 if (ps != null) {
5081 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
5082 if (ps.pkg != null && ps.pkg.applicationInfo != null) {
5083 systemApp = (ps.pkg.applicationInfo.flags &
5084 ApplicationInfo.FLAG_SYSTEM) != 0;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07005085 }
5086 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005087 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005088
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08005089 if (systemApp && onSd) {
5090 // Disable updates to system apps on sdcard
5091 Log.w(TAG, "Cannot install updates to system apps on sdcard");
5092 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
5093 return;
5094 }
5095 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
5096 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5097 return;
5098 }
5099 // Set application objects path explicitly after the rename
5100 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
5101 if(replace) {
5102 replacePackageLI(pkg, parseFlags, scanMode,
5103 installerPackageName, res);
5104 } else {
5105 installNewPackageLI(pkg, parseFlags, scanMode,
5106 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005107 }
5108 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005109
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005110 private int setPermissionsLI(PackageParser.Package newPackage) {
5111 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005112 int retCode = 0;
5113 // TODO Gross hack but fix later. Ideally move this to be a post installation
5114 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005115 if ((newPackage.applicationInfo.flags
5116 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
5117 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 try {
5119 extractPublicFiles(newPackage, destResourceFile);
5120 } catch (IOException e) {
5121 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
5122 " forward-locked app.");
5123 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
5124 } finally {
5125 //TODO clean up the extracted public files
5126 }
5127 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005128 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 newPackage.applicationInfo.uid);
5130 } else {
5131 final int filePermissions =
5132 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005133 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 newPackage.applicationInfo.uid);
5135 }
5136 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005137 // The permissions on the resource file was set when it was copied for
5138 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005141 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005142 Log.e(TAG, "Couldn't set new package file permissions for " +
5143 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005145 // TODO Define new internal error
5146 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 }
5148 return PackageManager.INSTALL_SUCCEEDED;
5149 }
5150
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005151 private boolean isForwardLocked(PackageParser.Package pkg) {
5152 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005153 }
5154
5155 private void extractPublicFiles(PackageParser.Package newPackage,
5156 File publicZipFile) throws IOException {
5157 final ZipOutputStream publicZipOutStream =
5158 new ZipOutputStream(new FileOutputStream(publicZipFile));
5159 final ZipFile privateZip = new ZipFile(newPackage.mPath);
5160
5161 // Copy manifest, resources.arsc and res directory to public zip
5162
5163 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
5164 while (privateZipEntries.hasMoreElements()) {
5165 final ZipEntry zipEntry = privateZipEntries.nextElement();
5166 final String zipEntryName = zipEntry.getName();
5167 if ("AndroidManifest.xml".equals(zipEntryName)
5168 || "resources.arsc".equals(zipEntryName)
5169 || zipEntryName.startsWith("res/")) {
5170 try {
5171 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
5172 } catch (IOException e) {
5173 try {
5174 publicZipOutStream.close();
5175 throw e;
5176 } finally {
5177 publicZipFile.delete();
5178 }
5179 }
5180 }
5181 }
5182
5183 publicZipOutStream.close();
5184 FileUtils.setPermissions(
5185 publicZipFile.getAbsolutePath(),
5186 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
5187 -1, -1);
5188 }
5189
5190 private static void copyZipEntry(ZipEntry zipEntry,
5191 ZipFile inZipFile,
5192 ZipOutputStream outZipStream) throws IOException {
5193 byte[] buffer = new byte[4096];
5194 int num;
5195
5196 ZipEntry newEntry;
5197 if (zipEntry.getMethod() == ZipEntry.STORED) {
5198 // Preserve the STORED method of the input entry.
5199 newEntry = new ZipEntry(zipEntry);
5200 } else {
5201 // Create a new entry so that the compressed len is recomputed.
5202 newEntry = new ZipEntry(zipEntry.getName());
5203 }
5204 outZipStream.putNextEntry(newEntry);
5205
5206 InputStream data = inZipFile.getInputStream(zipEntry);
5207 while ((num = data.read(buffer)) > 0) {
5208 outZipStream.write(buffer, 0, num);
5209 }
5210 outZipStream.flush();
5211 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 private void deleteTempPackageFiles() {
5214 FilenameFilter filter = new FilenameFilter() {
5215 public boolean accept(File dir, String name) {
5216 return name.startsWith("vmdl") && name.endsWith(".tmp");
5217 }
5218 };
5219 String tmpFilesList[] = mAppInstallDir.list(filter);
5220 if(tmpFilesList == null) {
5221 return;
5222 }
5223 for(int i = 0; i < tmpFilesList.length; i++) {
5224 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
5225 tmpFile.delete();
5226 }
5227 }
5228
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005229 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005230 File tmpPackageFile;
5231 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005232 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005233 } catch (IOException e) {
5234 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
5235 return null;
5236 }
5237 try {
5238 FileUtils.setPermissions(
5239 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
5240 -1, -1);
5241 } catch (IOException e) {
5242 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
5243 return null;
5244 }
5245 return tmpPackageFile;
5246 }
5247
5248 public void deletePackage(final String packageName,
5249 final IPackageDeleteObserver observer,
5250 final int flags) {
5251 mContext.enforceCallingOrSelfPermission(
5252 android.Manifest.permission.DELETE_PACKAGES, null);
5253 // Queue up an async operation since the package deletion may take a little while.
5254 mHandler.post(new Runnable() {
5255 public void run() {
5256 mHandler.removeCallbacks(this);
5257 final boolean succeded = deletePackageX(packageName, true, true, flags);
5258 if (observer != null) {
5259 try {
5260 observer.packageDeleted(succeded);
5261 } catch (RemoteException e) {
5262 Log.i(TAG, "Observer no longer exists.");
5263 } //end catch
5264 } //end if
5265 } //end run
5266 });
5267 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 /**
5270 * This method is an internal method that could be get invoked either
5271 * to delete an installed package or to clean up a failed installation.
5272 * After deleting an installed package, a broadcast is sent to notify any
5273 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005274 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005275 * installation wouldn't have sent the initial broadcast either
5276 * The key steps in deleting a package are
5277 * deleting the package information in internal structures like mPackages,
5278 * deleting the packages base directories through installd
5279 * updating mSettings to reflect current status
5280 * persisting settings for later use
5281 * sending a broadcast if necessary
5282 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 private boolean deletePackageX(String packageName, boolean sendBroadCast,
5284 boolean deleteCodeAndResources, int flags) {
5285 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07005286 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287
5288 synchronized (mInstallLock) {
5289 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
5290 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005292 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07005293 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
5294 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
5295
5296 // If the removed package was a system update, the old system packaged
5297 // was re-enabled; we need to broadcast this information
5298 if (systemUpdate) {
5299 Bundle extras = new Bundle(1);
5300 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
5301 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5302
5303 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
5304 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
5305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005306 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005307 // Delete the resources here after sending the broadcast to let
5308 // other processes clean up before deleting resources.
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08005309 if (info.args != null) {
5310 synchronized (mInstallLock) {
5311 info.args.doPostDeleteLI(deleteCodeAndResources);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005312 }
5313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 return res;
5315 }
5316
5317 static class PackageRemovedInfo {
5318 String removedPackage;
5319 int uid = -1;
5320 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07005321 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005322 // Clean up resources deleted packages.
5323 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07005324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 void sendBroadcast(boolean fullRemove, boolean replacing) {
5326 Bundle extras = new Bundle(1);
5327 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
5328 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
5329 if (replacing) {
5330 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5331 }
5332 if (removedPackage != null) {
5333 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
5334 }
5335 if (removedUid >= 0) {
5336 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5337 }
5338 }
5339 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005341 /*
5342 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5343 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005344 * 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 -08005345 * delete a partially installed application.
5346 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005347 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 int flags) {
5349 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005350 if (outInfo != null) {
5351 outInfo.removedPackage = packageName;
5352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 removePackageLI(p, true);
5354 // Retrieve object to delete permissions for shared user later on
5355 PackageSetting deletedPs;
5356 synchronized (mPackages) {
5357 deletedPs = mSettings.mPackages.get(packageName);
5358 }
5359 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005360 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005362 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 if (retCode < 0) {
5364 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5365 + packageName + ", retcode=" + retCode);
5366 // we don't consider this to be a failure of the core package deletion
5367 }
5368 } else {
5369 //for emulator
5370 PackageParser.Package pkg = mPackages.get(packageName);
5371 File dataDir = new File(pkg.applicationInfo.dataDir);
5372 dataDir.delete();
5373 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005374 schedulePackageCleaning(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005376 if (outInfo != null) {
5377 outInfo.removedUid = mSettings.removePackageLP(packageName);
5378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 }
5380 }
5381 synchronized (mPackages) {
5382 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5383 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005384 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 }
5386 // Save settings now
Dianne Hackborne83cefce2010-02-04 17:38:14 -08005387 mSettings.writeLP();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 }
5389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 /*
5392 * Tries to delete system package.
5393 */
5394 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005395 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 ApplicationInfo applicationInfo = p.applicationInfo;
5397 //applicable for non-partially installed applications only
5398 if (applicationInfo == null) {
5399 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5400 return false;
5401 }
5402 PackageSetting ps = null;
5403 // Confirm if the system package has been updated
5404 // An updated system app can be deleted. This will also have to restore
5405 // the system pkg from system partition
5406 synchronized (mPackages) {
5407 ps = mSettings.getDisabledSystemPkg(p.packageName);
5408 }
5409 if (ps == null) {
5410 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5411 return false;
5412 } else {
5413 Log.i(TAG, "Deleting system pkg from data partition");
5414 }
5415 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005416 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005417 boolean deleteCodeAndResources = false;
5418 if (ps.versionCode < p.mVersionCode) {
5419 // Delete code and resources for downgrades
5420 deleteCodeAndResources = true;
5421 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5422 flags &= ~PackageManager.DONT_DELETE_DATA;
5423 }
5424 } else {
5425 // Preserve data by setting flag
5426 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5427 flags |= PackageManager.DONT_DELETE_DATA;
5428 }
5429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005430 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5431 if (!ret) {
5432 return false;
5433 }
5434 synchronized (mPackages) {
5435 // Reinstate the old system package
5436 mSettings.enableSystemPackageLP(p.packageName);
5437 }
5438 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005439 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005440 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005441 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005443 if (newPkg == null) {
5444 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5445 return false;
5446 }
5447 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005448 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 mSettings.writeLP();
5450 }
5451 return true;
5452 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5455 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5456 ApplicationInfo applicationInfo = p.applicationInfo;
5457 if (applicationInfo == null) {
5458 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5459 return false;
5460 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005461 if (outInfo != null) {
5462 outInfo.uid = applicationInfo.uid;
5463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005464
5465 // Delete package data from internal structures and also remove data if flag is set
5466 removePackageDataLI(p, outInfo, flags);
5467
5468 // Delete application code and resources
5469 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005470 // TODO can pick up from PackageSettings as well
5471 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
5472 PackageManager.INSTALL_ON_SDCARD : 0;
5473 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5474 PackageManager.INSTALL_FORWARD_LOCK : 0;
5475 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005476 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 }
5478 return true;
5479 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 /*
5482 * This method handles package deletion in general
5483 */
5484 private boolean deletePackageLI(String packageName,
5485 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5486 if (packageName == null) {
5487 Log.w(TAG, "Attempt to delete null packageName.");
5488 return false;
5489 }
5490 PackageParser.Package p;
5491 boolean dataOnly = false;
5492 synchronized (mPackages) {
5493 p = mPackages.get(packageName);
5494 if (p == null) {
5495 //this retrieves partially installed apps
5496 dataOnly = true;
5497 PackageSetting ps = mSettings.mPackages.get(packageName);
5498 if (ps == null) {
5499 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5500 return false;
5501 }
5502 p = ps.pkg;
5503 }
5504 }
5505 if (p == null) {
5506 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5507 return false;
5508 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 if (dataOnly) {
5511 // Delete application data first
5512 removePackageDataLI(p, outInfo, flags);
5513 return true;
5514 }
5515 // At this point the package should have ApplicationInfo associated with it
5516 if (p.applicationInfo == null) {
5517 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5518 return false;
5519 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005520 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005521 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5522 Log.i(TAG, "Removing system package:"+p.packageName);
5523 // When an updated system application is deleted we delete the existing resources as well and
5524 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005525 ret = deleteSystemPackageLI(p, flags, outInfo);
5526 } else {
5527 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005528 // Kill application pre-emptively especially for apps on sd.
5529 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005530 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005531 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005532 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 public void clearApplicationUserData(final String packageName,
5536 final IPackageDataObserver observer) {
5537 mContext.enforceCallingOrSelfPermission(
5538 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
5539 // Queue up an async operation since the package deletion may take a little while.
5540 mHandler.post(new Runnable() {
5541 public void run() {
5542 mHandler.removeCallbacks(this);
5543 final boolean succeeded;
5544 synchronized (mInstallLock) {
5545 succeeded = clearApplicationUserDataLI(packageName);
5546 }
5547 if (succeeded) {
5548 // invoke DeviceStorageMonitor's update method to clear any notifications
5549 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
5550 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
5551 if (dsm != null) {
5552 dsm.updateMemory();
5553 }
5554 }
5555 if(observer != null) {
5556 try {
5557 observer.onRemoveCompleted(packageName, succeeded);
5558 } catch (RemoteException e) {
5559 Log.i(TAG, "Observer no longer exists.");
5560 }
5561 } //end if observer
5562 } //end run
5563 });
5564 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005566 private boolean clearApplicationUserDataLI(String packageName) {
5567 if (packageName == null) {
5568 Log.w(TAG, "Attempt to delete null packageName.");
5569 return false;
5570 }
5571 PackageParser.Package p;
5572 boolean dataOnly = false;
5573 synchronized (mPackages) {
5574 p = mPackages.get(packageName);
5575 if(p == null) {
5576 dataOnly = true;
5577 PackageSetting ps = mSettings.mPackages.get(packageName);
5578 if((ps == null) || (ps.pkg == null)) {
5579 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5580 return false;
5581 }
5582 p = ps.pkg;
5583 }
5584 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005585 boolean useEncryptedFSDir = false;
5586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005587 if(!dataOnly) {
5588 //need to check this only for fully installed applications
5589 if (p == null) {
5590 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5591 return false;
5592 }
5593 final ApplicationInfo applicationInfo = p.applicationInfo;
5594 if (applicationInfo == null) {
5595 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5596 return false;
5597 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005598 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005599 }
5600 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005601 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 if (retCode < 0) {
5603 Log.w(TAG, "Couldn't remove cache files for package: "
5604 + packageName);
5605 return false;
5606 }
5607 }
5608 return true;
5609 }
5610
5611 public void deleteApplicationCacheFiles(final String packageName,
5612 final IPackageDataObserver observer) {
5613 mContext.enforceCallingOrSelfPermission(
5614 android.Manifest.permission.DELETE_CACHE_FILES, null);
5615 // Queue up an async operation since the package deletion may take a little while.
5616 mHandler.post(new Runnable() {
5617 public void run() {
5618 mHandler.removeCallbacks(this);
5619 final boolean succeded;
5620 synchronized (mInstallLock) {
5621 succeded = deleteApplicationCacheFilesLI(packageName);
5622 }
5623 if(observer != null) {
5624 try {
5625 observer.onRemoveCompleted(packageName, succeded);
5626 } catch (RemoteException e) {
5627 Log.i(TAG, "Observer no longer exists.");
5628 }
5629 } //end if observer
5630 } //end run
5631 });
5632 }
5633
5634 private boolean deleteApplicationCacheFilesLI(String packageName) {
5635 if (packageName == null) {
5636 Log.w(TAG, "Attempt to delete null packageName.");
5637 return false;
5638 }
5639 PackageParser.Package p;
5640 synchronized (mPackages) {
5641 p = mPackages.get(packageName);
5642 }
5643 if (p == null) {
5644 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5645 return false;
5646 }
5647 final ApplicationInfo applicationInfo = p.applicationInfo;
5648 if (applicationInfo == null) {
5649 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5650 return false;
5651 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005652 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005654 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 if (retCode < 0) {
5656 Log.w(TAG, "Couldn't remove cache files for package: "
5657 + packageName);
5658 return false;
5659 }
5660 }
5661 return true;
5662 }
5663
5664 public void getPackageSizeInfo(final String packageName,
5665 final IPackageStatsObserver observer) {
5666 mContext.enforceCallingOrSelfPermission(
5667 android.Manifest.permission.GET_PACKAGE_SIZE, null);
5668 // Queue up an async operation since the package deletion may take a little while.
5669 mHandler.post(new Runnable() {
5670 public void run() {
5671 mHandler.removeCallbacks(this);
5672 PackageStats lStats = new PackageStats(packageName);
5673 final boolean succeded;
5674 synchronized (mInstallLock) {
5675 succeded = getPackageSizeInfoLI(packageName, lStats);
5676 }
5677 if(observer != null) {
5678 try {
5679 observer.onGetStatsCompleted(lStats, succeded);
5680 } catch (RemoteException e) {
5681 Log.i(TAG, "Observer no longer exists.");
5682 }
5683 } //end if observer
5684 } //end run
5685 });
5686 }
5687
5688 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
5689 if (packageName == null) {
5690 Log.w(TAG, "Attempt to get size of null packageName.");
5691 return false;
5692 }
5693 PackageParser.Package p;
5694 boolean dataOnly = false;
5695 synchronized (mPackages) {
5696 p = mPackages.get(packageName);
5697 if(p == null) {
5698 dataOnly = true;
5699 PackageSetting ps = mSettings.mPackages.get(packageName);
5700 if((ps == null) || (ps.pkg == null)) {
5701 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5702 return false;
5703 }
5704 p = ps.pkg;
5705 }
5706 }
5707 String publicSrcDir = null;
5708 if(!dataOnly) {
5709 final ApplicationInfo applicationInfo = p.applicationInfo;
5710 if (applicationInfo == null) {
5711 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5712 return false;
5713 }
5714 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
5715 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005716 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 if (mInstaller != null) {
5718 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08005719 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 if (res < 0) {
5721 return false;
5722 } else {
5723 return true;
5724 }
5725 }
5726 return true;
5727 }
5728
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 public void addPackageToPreferred(String packageName) {
5731 mContext.enforceCallingOrSelfPermission(
5732 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005733 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 }
5735
5736 public void removePackageFromPreferred(String packageName) {
5737 mContext.enforceCallingOrSelfPermission(
5738 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005739 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005740 }
5741
5742 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005743 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 }
5745
5746 public void addPreferredActivity(IntentFilter filter, int match,
5747 ComponentName[] set, ComponentName activity) {
5748 mContext.enforceCallingOrSelfPermission(
5749 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5750
5751 synchronized (mPackages) {
5752 Log.i(TAG, "Adding preferred activity " + activity + ":");
5753 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5754 mSettings.mPreferredActivities.addFilter(
5755 new PreferredActivity(filter, match, set, activity));
5756 mSettings.writeLP();
5757 }
5758 }
5759
Satish Sampath8dbe6122009-06-02 23:35:54 +01005760 public void replacePreferredActivity(IntentFilter filter, int match,
5761 ComponentName[] set, ComponentName activity) {
5762 mContext.enforceCallingOrSelfPermission(
5763 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5764 if (filter.countActions() != 1) {
5765 throw new IllegalArgumentException(
5766 "replacePreferredActivity expects filter to have only 1 action.");
5767 }
5768 if (filter.countCategories() != 1) {
5769 throw new IllegalArgumentException(
5770 "replacePreferredActivity expects filter to have only 1 category.");
5771 }
5772 if (filter.countDataAuthorities() != 0
5773 || filter.countDataPaths() != 0
5774 || filter.countDataSchemes() != 0
5775 || filter.countDataTypes() != 0) {
5776 throw new IllegalArgumentException(
5777 "replacePreferredActivity expects filter to have no data authorities, " +
5778 "paths, schemes or types.");
5779 }
5780 synchronized (mPackages) {
5781 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5782 String action = filter.getAction(0);
5783 String category = filter.getCategory(0);
5784 while (it.hasNext()) {
5785 PreferredActivity pa = it.next();
5786 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5787 it.remove();
5788 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5789 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5790 }
5791 }
5792 addPreferredActivity(filter, match, set, activity);
5793 }
5794 }
5795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005796 public void clearPackagePreferredActivities(String packageName) {
5797 mContext.enforceCallingOrSelfPermission(
5798 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5799
5800 synchronized (mPackages) {
5801 if (clearPackagePreferredActivitiesLP(packageName)) {
5802 mSettings.writeLP();
5803 }
5804 }
5805 }
5806
5807 boolean clearPackagePreferredActivitiesLP(String packageName) {
5808 boolean changed = false;
5809 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5810 while (it.hasNext()) {
5811 PreferredActivity pa = it.next();
5812 if (pa.mActivity.getPackageName().equals(packageName)) {
5813 it.remove();
5814 changed = true;
5815 }
5816 }
5817 return changed;
5818 }
5819
5820 public int getPreferredActivities(List<IntentFilter> outFilters,
5821 List<ComponentName> outActivities, String packageName) {
5822
5823 int num = 0;
5824 synchronized (mPackages) {
5825 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5826 while (it.hasNext()) {
5827 PreferredActivity pa = it.next();
5828 if (packageName == null
5829 || pa.mActivity.getPackageName().equals(packageName)) {
5830 if (outFilters != null) {
5831 outFilters.add(new IntentFilter(pa));
5832 }
5833 if (outActivities != null) {
5834 outActivities.add(pa.mActivity);
5835 }
5836 }
5837 }
5838 }
5839
5840 return num;
5841 }
5842
5843 public void setApplicationEnabledSetting(String appPackageName,
5844 int newState, int flags) {
5845 setEnabledSetting(appPackageName, null, newState, flags);
5846 }
5847
5848 public void setComponentEnabledSetting(ComponentName componentName,
5849 int newState, int flags) {
5850 setEnabledSetting(componentName.getPackageName(),
5851 componentName.getClassName(), newState, flags);
5852 }
5853
5854 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005855 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5857 || newState == COMPONENT_ENABLED_STATE_ENABLED
5858 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5859 throw new IllegalArgumentException("Invalid new component state: "
5860 + newState);
5861 }
5862 PackageSetting pkgSetting;
5863 final int uid = Binder.getCallingUid();
5864 final int permission = mContext.checkCallingPermission(
5865 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5866 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005867 boolean sendNow = false;
5868 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005869 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005871 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005873 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005874 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005875 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005877 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 }
5879 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005880 "Unknown component: " + packageName
5881 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005882 }
5883 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5884 throw new SecurityException(
5885 "Permission Denial: attempt to change component state from pid="
5886 + Binder.getCallingPid()
5887 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5888 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005889 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 // We're dealing with an application/package level state change
5891 pkgSetting.enabled = newState;
5892 } else {
5893 // We're dealing with a component level state change
5894 switch (newState) {
5895 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005896 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 break;
5898 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005899 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005900 break;
5901 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005902 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 break;
5904 default:
5905 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005906 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 }
5908 }
5909 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005910 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005911 components = mPendingBroadcasts.get(packageName);
5912 boolean newPackage = components == null;
5913 if (newPackage) {
5914 components = new ArrayList<String>();
5915 }
5916 if (!components.contains(componentName)) {
5917 components.add(componentName);
5918 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005919 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5920 sendNow = true;
5921 // Purge entry from pending broadcast list if another one exists already
5922 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005923 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005924 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005925 if (newPackage) {
5926 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005927 }
5928 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5929 // Schedule a message
5930 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5931 }
5932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 long callingId = Binder.clearCallingIdentity();
5936 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005937 if (sendNow) {
5938 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005939 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 } finally {
5942 Binder.restoreCallingIdentity(callingId);
5943 }
5944 }
5945
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005946 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005947 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5948 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5949 + " components=" + componentNames);
5950 Bundle extras = new Bundle(4);
5951 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5952 String nameList[] = new String[componentNames.size()];
5953 componentNames.toArray(nameList);
5954 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005955 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5956 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005957 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005958 }
5959
Jacek Surazski65e13172009-04-28 15:26:38 +02005960 public String getInstallerPackageName(String packageName) {
5961 synchronized (mPackages) {
5962 PackageSetting pkg = mSettings.mPackages.get(packageName);
5963 if (pkg == null) {
5964 throw new IllegalArgumentException("Unknown package: " + packageName);
5965 }
5966 return pkg.installerPackageName;
5967 }
5968 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005970 public int getApplicationEnabledSetting(String appPackageName) {
5971 synchronized (mPackages) {
5972 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5973 if (pkg == null) {
5974 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5975 }
5976 return pkg.enabled;
5977 }
5978 }
5979
5980 public int getComponentEnabledSetting(ComponentName componentName) {
5981 synchronized (mPackages) {
5982 final String packageNameStr = componentName.getPackageName();
5983 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5984 if (pkg == null) {
5985 throw new IllegalArgumentException("Unknown component: " + componentName);
5986 }
5987 final String classNameStr = componentName.getClassName();
5988 return pkg.currentEnabledStateLP(classNameStr);
5989 }
5990 }
5991
5992 public void enterSafeMode() {
5993 if (!mSystemReady) {
5994 mSafeMode = true;
5995 }
5996 }
5997
5998 public void systemReady() {
5999 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006000
6001 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006002 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006003 mContext.getContentResolver(),
6004 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006005 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006006 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07006007 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07006008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006009 }
6010
6011 public boolean isSafeMode() {
6012 return mSafeMode;
6013 }
6014
6015 public boolean hasSystemUidErrors() {
6016 return mHasSystemUidErrors;
6017 }
6018
6019 static String arrayToString(int[] array) {
6020 StringBuffer buf = new StringBuffer(128);
6021 buf.append('[');
6022 if (array != null) {
6023 for (int i=0; i<array.length; i++) {
6024 if (i > 0) buf.append(", ");
6025 buf.append(array[i]);
6026 }
6027 }
6028 buf.append(']');
6029 return buf.toString();
6030 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 @Override
6033 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
6034 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6035 != PackageManager.PERMISSION_GRANTED) {
6036 pw.println("Permission Denial: can't dump ActivityManager from from pid="
6037 + Binder.getCallingPid()
6038 + ", uid=" + Binder.getCallingUid()
6039 + " without permission "
6040 + android.Manifest.permission.DUMP);
6041 return;
6042 }
6043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 synchronized (mPackages) {
6045 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006046 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 pw.println(" ");
6048 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006049 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006050 pw.println(" ");
6051 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006052 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 pw.println(" ");
6054 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006055 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006057 pw.println("Permissions:");
6058 {
6059 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006060 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
6061 pw.print(Integer.toHexString(System.identityHashCode(p)));
6062 pw.println("):");
6063 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
6064 pw.print(" uid="); pw.print(p.uid);
6065 pw.print(" gids="); pw.print(arrayToString(p.gids));
6066 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 }
6068 }
6069 pw.println(" ");
6070 pw.println("Packages:");
6071 {
6072 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006073 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
6074 pw.print(Integer.toHexString(System.identityHashCode(ps)));
6075 pw.println("):");
6076 pw.print(" userId="); pw.print(ps.userId);
6077 pw.print(" gids="); pw.println(arrayToString(ps.gids));
6078 pw.print(" sharedUser="); pw.println(ps.sharedUser);
6079 pw.print(" pkg="); pw.println(ps.pkg);
6080 pw.print(" codePath="); pw.println(ps.codePathString);
6081 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006082 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006083 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006084 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006085 pw.print(" supportsScreens=[");
6086 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006087 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006088 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006089 if (!first) pw.print(", ");
6090 first = false;
6091 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006092 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006093 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006094 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006095 if (!first) pw.print(", ");
6096 first = false;
6097 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006098 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006099 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006100 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006101 if (!first) pw.print(", ");
6102 first = false;
6103 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07006104 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006105 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006106 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006107 if (!first) pw.print(", ");
6108 first = false;
6109 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07006110 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006111 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006112 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
6113 if (!first) pw.print(", ");
6114 first = false;
6115 pw.print("anyDensity");
6116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07006118 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006119 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
6120 pw.print(" signatures="); pw.println(ps.signatures);
6121 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
6122 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
6123 pw.print(" installStatus="); pw.print(ps.installStatus);
6124 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 if (ps.disabledComponents.size() > 0) {
6126 pw.println(" disabledComponents:");
6127 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006128 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 }
6130 }
6131 if (ps.enabledComponents.size() > 0) {
6132 pw.println(" enabledComponents:");
6133 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006134 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 }
6136 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006137 if (ps.grantedPermissions.size() > 0) {
6138 pw.println(" grantedPermissions:");
6139 for (String s : ps.grantedPermissions) {
6140 pw.print(" "); pw.println(s);
6141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006142 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006143 if (ps.loadedPermissions.size() > 0) {
6144 pw.println(" loadedPermissions:");
6145 for (String s : ps.loadedPermissions) {
6146 pw.print(" "); pw.println(s);
6147 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 }
6149 }
6150 }
6151 pw.println(" ");
6152 pw.println("Shared Users:");
6153 {
6154 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006155 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
6156 pw.print(Integer.toHexString(System.identityHashCode(su)));
6157 pw.println("):");
6158 pw.print(" userId="); pw.print(su.userId);
6159 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 pw.println(" grantedPermissions:");
6161 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006162 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006163 }
6164 pw.println(" loadedPermissions:");
6165 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006166 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 }
6168 }
6169 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 pw.println(" ");
6172 pw.println("Settings parse messages:");
6173 pw.println(mSettings.mReadMessages.toString());
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006174
6175 pw.println(" ");
6176 pw.println("Package warning messages:");
6177 File fname = getSettingsProblemFile();
6178 FileInputStream in;
6179 try {
6180 in = new FileInputStream(fname);
6181 int avail = in.available();
6182 byte[] data = new byte[avail];
6183 in.read(data);
6184 pw.println(new String(data));
6185 } catch (FileNotFoundException e) {
6186 } catch (IOException e) {
6187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006188 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006189
6190 synchronized (mProviders) {
6191 pw.println(" ");
6192 pw.println("Registered ContentProviders:");
6193 for (PackageParser.Provider p : mProviders.values()) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006194 pw.print(" ["); pw.print(p.info.authority); pw.print("]: ");
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05006195 pw.println(p.toString());
6196 }
6197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006198 }
6199
6200 static final class BasePermission {
6201 final static int TYPE_NORMAL = 0;
6202 final static int TYPE_BUILTIN = 1;
6203 final static int TYPE_DYNAMIC = 2;
6204
6205 final String name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006206 String sourcePackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006207 final int type;
6208 PackageParser.Permission perm;
6209 PermissionInfo pendingInfo;
6210 int uid;
6211 int[] gids;
6212
6213 BasePermission(String _name, String _sourcePackage, int _type) {
6214 name = _name;
6215 sourcePackage = _sourcePackage;
6216 type = _type;
6217 }
6218 }
6219
6220 static class PackageSignatures {
6221 private Signature[] mSignatures;
6222
6223 PackageSignatures(Signature[] sigs) {
6224 assignSignatures(sigs);
6225 }
6226
6227 PackageSignatures() {
6228 }
6229
6230 void writeXml(XmlSerializer serializer, String tagName,
6231 ArrayList<Signature> pastSignatures) throws IOException {
6232 if (mSignatures == null) {
6233 return;
6234 }
6235 serializer.startTag(null, tagName);
6236 serializer.attribute(null, "count",
6237 Integer.toString(mSignatures.length));
6238 for (int i=0; i<mSignatures.length; i++) {
6239 serializer.startTag(null, "cert");
6240 final Signature sig = mSignatures[i];
6241 final int sigHash = sig.hashCode();
6242 final int numPast = pastSignatures.size();
6243 int j;
6244 for (j=0; j<numPast; j++) {
6245 Signature pastSig = pastSignatures.get(j);
6246 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
6247 serializer.attribute(null, "index", Integer.toString(j));
6248 break;
6249 }
6250 }
6251 if (j >= numPast) {
6252 pastSignatures.add(sig);
6253 serializer.attribute(null, "index", Integer.toString(numPast));
6254 serializer.attribute(null, "key", sig.toCharsString());
6255 }
6256 serializer.endTag(null, "cert");
6257 }
6258 serializer.endTag(null, tagName);
6259 }
6260
6261 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
6262 throws IOException, XmlPullParserException {
6263 String countStr = parser.getAttributeValue(null, "count");
6264 if (countStr == null) {
6265 reportSettingsProblem(Log.WARN,
6266 "Error in package manager settings: <signatures> has"
6267 + " no count at " + parser.getPositionDescription());
6268 XmlUtils.skipCurrentTag(parser);
6269 }
6270 final int count = Integer.parseInt(countStr);
6271 mSignatures = new Signature[count];
6272 int pos = 0;
6273
6274 int outerDepth = parser.getDepth();
6275 int type;
6276 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6277 && (type != XmlPullParser.END_TAG
6278 || parser.getDepth() > outerDepth)) {
6279 if (type == XmlPullParser.END_TAG
6280 || type == XmlPullParser.TEXT) {
6281 continue;
6282 }
6283
6284 String tagName = parser.getName();
6285 if (tagName.equals("cert")) {
6286 if (pos < count) {
6287 String index = parser.getAttributeValue(null, "index");
6288 if (index != null) {
6289 try {
6290 int idx = Integer.parseInt(index);
6291 String key = parser.getAttributeValue(null, "key");
6292 if (key == null) {
6293 if (idx >= 0 && idx < pastSignatures.size()) {
6294 Signature sig = pastSignatures.get(idx);
6295 if (sig != null) {
6296 mSignatures[pos] = pastSignatures.get(idx);
6297 pos++;
6298 } else {
6299 reportSettingsProblem(Log.WARN,
6300 "Error in package manager settings: <cert> "
6301 + "index " + index + " is not defined at "
6302 + parser.getPositionDescription());
6303 }
6304 } else {
6305 reportSettingsProblem(Log.WARN,
6306 "Error in package manager settings: <cert> "
6307 + "index " + index + " is out of bounds at "
6308 + parser.getPositionDescription());
6309 }
6310 } else {
6311 while (pastSignatures.size() <= idx) {
6312 pastSignatures.add(null);
6313 }
6314 Signature sig = new Signature(key);
6315 pastSignatures.set(idx, sig);
6316 mSignatures[pos] = sig;
6317 pos++;
6318 }
6319 } catch (NumberFormatException e) {
6320 reportSettingsProblem(Log.WARN,
6321 "Error in package manager settings: <cert> "
6322 + "index " + index + " is not a number at "
6323 + parser.getPositionDescription());
6324 }
6325 } else {
6326 reportSettingsProblem(Log.WARN,
6327 "Error in package manager settings: <cert> has"
6328 + " no index at " + parser.getPositionDescription());
6329 }
6330 } else {
6331 reportSettingsProblem(Log.WARN,
6332 "Error in package manager settings: too "
6333 + "many <cert> tags, expected " + count
6334 + " at " + parser.getPositionDescription());
6335 }
6336 } else {
6337 reportSettingsProblem(Log.WARN,
6338 "Unknown element under <cert>: "
6339 + parser.getName());
6340 }
6341 XmlUtils.skipCurrentTag(parser);
6342 }
6343
6344 if (pos < count) {
6345 // Should never happen -- there is an error in the written
6346 // settings -- but if it does we don't want to generate
6347 // a bad array.
6348 Signature[] newSigs = new Signature[pos];
6349 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
6350 mSignatures = newSigs;
6351 }
6352 }
6353
6354 /**
6355 * If any of the given 'sigs' is contained in the existing signatures,
6356 * then completely replace the current signatures with the ones in
6357 * 'sigs'. This is used for updating an existing package to a newly
6358 * installed version.
6359 */
6360 boolean updateSignatures(Signature[] sigs, boolean update) {
6361 if (mSignatures == null) {
6362 if (update) {
6363 assignSignatures(sigs);
6364 }
6365 return true;
6366 }
6367 if (sigs == null) {
6368 return false;
6369 }
6370
6371 for (int i=0; i<sigs.length; i++) {
6372 Signature sig = sigs[i];
6373 for (int j=0; j<mSignatures.length; j++) {
6374 if (mSignatures[j].equals(sig)) {
6375 if (update) {
6376 assignSignatures(sigs);
6377 }
6378 return true;
6379 }
6380 }
6381 }
6382 return false;
6383 }
6384
6385 /**
6386 * If any of the given 'sigs' is contained in the existing signatures,
6387 * then add in any new signatures found in 'sigs'. This is used for
6388 * including a new package into an existing shared user id.
6389 */
6390 boolean mergeSignatures(Signature[] sigs, boolean update) {
6391 if (mSignatures == null) {
6392 if (update) {
6393 assignSignatures(sigs);
6394 }
6395 return true;
6396 }
6397 if (sigs == null) {
6398 return false;
6399 }
6400
6401 Signature[] added = null;
6402 int addedCount = 0;
6403 boolean haveMatch = false;
6404 for (int i=0; i<sigs.length; i++) {
6405 Signature sig = sigs[i];
6406 boolean found = false;
6407 for (int j=0; j<mSignatures.length; j++) {
6408 if (mSignatures[j].equals(sig)) {
6409 found = true;
6410 haveMatch = true;
6411 break;
6412 }
6413 }
6414
6415 if (!found) {
6416 if (added == null) {
6417 added = new Signature[sigs.length];
6418 }
6419 added[i] = sig;
6420 addedCount++;
6421 }
6422 }
6423
6424 if (!haveMatch) {
6425 // Nothing matched -- reject the new signatures.
6426 return false;
6427 }
6428 if (added == null) {
6429 // Completely matched -- nothing else to do.
6430 return true;
6431 }
6432
6433 // Add additional signatures in.
6434 if (update) {
6435 Signature[] total = new Signature[addedCount+mSignatures.length];
6436 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6437 int j = mSignatures.length;
6438 for (int i=0; i<added.length; i++) {
6439 if (added[i] != null) {
6440 total[j] = added[i];
6441 j++;
6442 }
6443 }
6444 mSignatures = total;
6445 }
6446 return true;
6447 }
6448
6449 private void assignSignatures(Signature[] sigs) {
6450 if (sigs == null) {
6451 mSignatures = null;
6452 return;
6453 }
6454 mSignatures = new Signature[sigs.length];
6455 for (int i=0; i<sigs.length; i++) {
6456 mSignatures[i] = sigs[i];
6457 }
6458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 @Override
6461 public String toString() {
6462 StringBuffer buf = new StringBuffer(128);
6463 buf.append("PackageSignatures{");
6464 buf.append(Integer.toHexString(System.identityHashCode(this)));
6465 buf.append(" [");
6466 if (mSignatures != null) {
6467 for (int i=0; i<mSignatures.length; i++) {
6468 if (i > 0) buf.append(", ");
6469 buf.append(Integer.toHexString(
6470 System.identityHashCode(mSignatures[i])));
6471 }
6472 }
6473 buf.append("]}");
6474 return buf.toString();
6475 }
6476 }
6477
6478 static class PreferredActivity extends IntentFilter {
6479 final int mMatch;
6480 final String[] mSetPackages;
6481 final String[] mSetClasses;
6482 final String[] mSetComponents;
6483 final ComponentName mActivity;
6484 final String mShortActivity;
6485 String mParseError;
6486
6487 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6488 ComponentName activity) {
6489 super(filter);
6490 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6491 mActivity = activity;
6492 mShortActivity = activity.flattenToShortString();
6493 mParseError = null;
6494 if (set != null) {
6495 final int N = set.length;
6496 String[] myPackages = new String[N];
6497 String[] myClasses = new String[N];
6498 String[] myComponents = new String[N];
6499 for (int i=0; i<N; i++) {
6500 ComponentName cn = set[i];
6501 if (cn == null) {
6502 mSetPackages = null;
6503 mSetClasses = null;
6504 mSetComponents = null;
6505 return;
6506 }
6507 myPackages[i] = cn.getPackageName().intern();
6508 myClasses[i] = cn.getClassName().intern();
6509 myComponents[i] = cn.flattenToShortString().intern();
6510 }
6511 mSetPackages = myPackages;
6512 mSetClasses = myClasses;
6513 mSetComponents = myComponents;
6514 } else {
6515 mSetPackages = null;
6516 mSetClasses = null;
6517 mSetComponents = null;
6518 }
6519 }
6520
6521 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
6522 IOException {
6523 mShortActivity = parser.getAttributeValue(null, "name");
6524 mActivity = ComponentName.unflattenFromString(mShortActivity);
6525 if (mActivity == null) {
6526 mParseError = "Bad activity name " + mShortActivity;
6527 }
6528 String matchStr = parser.getAttributeValue(null, "match");
6529 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
6530 String setCountStr = parser.getAttributeValue(null, "set");
6531 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
6532
6533 String[] myPackages = setCount > 0 ? new String[setCount] : null;
6534 String[] myClasses = setCount > 0 ? new String[setCount] : null;
6535 String[] myComponents = setCount > 0 ? new String[setCount] : null;
6536
6537 int setPos = 0;
6538
6539 int outerDepth = parser.getDepth();
6540 int type;
6541 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6542 && (type != XmlPullParser.END_TAG
6543 || parser.getDepth() > outerDepth)) {
6544 if (type == XmlPullParser.END_TAG
6545 || type == XmlPullParser.TEXT) {
6546 continue;
6547 }
6548
6549 String tagName = parser.getName();
6550 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
6551 // + parser.getDepth() + " tag=" + tagName);
6552 if (tagName.equals("set")) {
6553 String name = parser.getAttributeValue(null, "name");
6554 if (name == null) {
6555 if (mParseError == null) {
6556 mParseError = "No name in set tag in preferred activity "
6557 + mShortActivity;
6558 }
6559 } else if (setPos >= setCount) {
6560 if (mParseError == null) {
6561 mParseError = "Too many set tags in preferred activity "
6562 + mShortActivity;
6563 }
6564 } else {
6565 ComponentName cn = ComponentName.unflattenFromString(name);
6566 if (cn == null) {
6567 if (mParseError == null) {
6568 mParseError = "Bad set name " + name + " in preferred activity "
6569 + mShortActivity;
6570 }
6571 } else {
6572 myPackages[setPos] = cn.getPackageName();
6573 myClasses[setPos] = cn.getClassName();
6574 myComponents[setPos] = name;
6575 setPos++;
6576 }
6577 }
6578 XmlUtils.skipCurrentTag(parser);
6579 } else if (tagName.equals("filter")) {
6580 //Log.i(TAG, "Starting to parse filter...");
6581 readFromXml(parser);
6582 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
6583 // + parser.getDepth() + " tag=" + parser.getName());
6584 } else {
6585 reportSettingsProblem(Log.WARN,
6586 "Unknown element under <preferred-activities>: "
6587 + parser.getName());
6588 XmlUtils.skipCurrentTag(parser);
6589 }
6590 }
6591
6592 if (setPos != setCount) {
6593 if (mParseError == null) {
6594 mParseError = "Not enough set tags (expected " + setCount
6595 + " but found " + setPos + ") in " + mShortActivity;
6596 }
6597 }
6598
6599 mSetPackages = myPackages;
6600 mSetClasses = myClasses;
6601 mSetComponents = myComponents;
6602 }
6603
6604 public void writeToXml(XmlSerializer serializer) throws IOException {
6605 final int NS = mSetClasses != null ? mSetClasses.length : 0;
6606 serializer.attribute(null, "name", mShortActivity);
6607 serializer.attribute(null, "match", Integer.toHexString(mMatch));
6608 serializer.attribute(null, "set", Integer.toString(NS));
6609 for (int s=0; s<NS; s++) {
6610 serializer.startTag(null, "set");
6611 serializer.attribute(null, "name", mSetComponents[s]);
6612 serializer.endTag(null, "set");
6613 }
6614 serializer.startTag(null, "filter");
6615 super.writeToXml(serializer);
6616 serializer.endTag(null, "filter");
6617 }
6618
6619 boolean sameSet(List<ResolveInfo> query, int priority) {
6620 if (mSetPackages == null) return false;
6621 final int NQ = query.size();
6622 final int NS = mSetPackages.length;
6623 int numMatch = 0;
6624 for (int i=0; i<NQ; i++) {
6625 ResolveInfo ri = query.get(i);
6626 if (ri.priority != priority) continue;
6627 ActivityInfo ai = ri.activityInfo;
6628 boolean good = false;
6629 for (int j=0; j<NS; j++) {
6630 if (mSetPackages[j].equals(ai.packageName)
6631 && mSetClasses[j].equals(ai.name)) {
6632 numMatch++;
6633 good = true;
6634 break;
6635 }
6636 }
6637 if (!good) return false;
6638 }
6639 return numMatch == NS;
6640 }
6641 }
6642
6643 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006644 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 HashSet<String> grantedPermissions = new HashSet<String>();
6647 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08006652 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
6653 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
6654 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 }
6656 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 /**
6659 * Settings base class for pending and resolved classes.
6660 */
6661 static class PackageSettingBase extends GrantedPermissions {
6662 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006663 File codePath;
6664 String codePathString;
6665 File resourcePath;
6666 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 private long timeStamp;
6668 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006669 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006670
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006671 boolean uidError;
6672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006673 PackageSignatures signatures = new PackageSignatures();
6674
6675 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 /* Explicitly disabled components */
6678 HashSet<String> disabledComponents = new HashSet<String>(0);
6679 /* Explicitly enabled components */
6680 HashSet<String> enabledComponents = new HashSet<String>(0);
6681 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6682 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006683
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006684 PackageSettingBase origPackage;
6685
Jacek Surazski65e13172009-04-28 15:26:38 +02006686 /* package name of the app that installed this package */
6687 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688
6689 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006690 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006691 super(pkgFlags);
6692 this.name = name;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006693 init(codePath, resourcePath, pVersionCode);
6694 }
6695
6696 void init(File codePath, File resourcePath, int pVersionCode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 this.codePath = codePath;
6698 this.codePathString = codePath.toString();
6699 this.resourcePath = resourcePath;
6700 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006701 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006703
Jacek Surazski65e13172009-04-28 15:26:38 +02006704 public void setInstallerPackageName(String packageName) {
6705 installerPackageName = packageName;
6706 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006707
Jacek Surazski65e13172009-04-28 15:26:38 +02006708 String getInstallerPackageName() {
6709 return installerPackageName;
6710 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 public void setInstallStatus(int newStatus) {
6713 installStatus = newStatus;
6714 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006716 public int getInstallStatus() {
6717 return installStatus;
6718 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 public void setTimeStamp(long newStamp) {
6721 if (newStamp != timeStamp) {
6722 timeStamp = newStamp;
6723 timeStampString = Long.toString(newStamp);
6724 }
6725 }
6726
6727 public void setTimeStamp(long newStamp, String newStampStr) {
6728 timeStamp = newStamp;
6729 timeStampString = newStampStr;
6730 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 public long getTimeStamp() {
6733 return timeStamp;
6734 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006736 public String getTimeStampStr() {
6737 return timeStampString;
6738 }
6739
6740 public void copyFrom(PackageSettingBase base) {
6741 grantedPermissions = base.grantedPermissions;
6742 gids = base.gids;
6743 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006745 timeStamp = base.timeStamp;
6746 timeStampString = base.timeStampString;
6747 signatures = base.signatures;
6748 permissionsFixed = base.permissionsFixed;
6749 disabledComponents = base.disabledComponents;
6750 enabledComponents = base.enabledComponents;
6751 enabled = base.enabled;
6752 installStatus = base.installStatus;
6753 }
6754
6755 void enableComponentLP(String componentClassName) {
6756 disabledComponents.remove(componentClassName);
6757 enabledComponents.add(componentClassName);
6758 }
6759
6760 void disableComponentLP(String componentClassName) {
6761 enabledComponents.remove(componentClassName);
6762 disabledComponents.add(componentClassName);
6763 }
6764
6765 void restoreComponentLP(String componentClassName) {
6766 enabledComponents.remove(componentClassName);
6767 disabledComponents.remove(componentClassName);
6768 }
6769
6770 int currentEnabledStateLP(String componentName) {
6771 if (enabledComponents.contains(componentName)) {
6772 return COMPONENT_ENABLED_STATE_ENABLED;
6773 } else if (disabledComponents.contains(componentName)) {
6774 return COMPONENT_ENABLED_STATE_DISABLED;
6775 } else {
6776 return COMPONENT_ENABLED_STATE_DEFAULT;
6777 }
6778 }
6779 }
6780
6781 /**
6782 * Settings data for a particular package we know about.
6783 */
6784 static final class PackageSetting extends PackageSettingBase {
6785 int userId;
6786 PackageParser.Package pkg;
6787 SharedUserSetting sharedUser;
6788
6789 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006790 int pVersionCode, int pkgFlags) {
6791 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006792 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006794 @Override
6795 public String toString() {
6796 return "PackageSetting{"
6797 + Integer.toHexString(System.identityHashCode(this))
6798 + " " + name + "/" + userId + "}";
6799 }
6800 }
6801
6802 /**
6803 * Settings data for a particular shared user ID we know about.
6804 */
6805 static final class SharedUserSetting extends GrantedPermissions {
6806 final String name;
6807 int userId;
6808 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6809 final PackageSignatures signatures = new PackageSignatures();
6810
6811 SharedUserSetting(String _name, int _pkgFlags) {
6812 super(_pkgFlags);
6813 name = _name;
6814 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 @Override
6817 public String toString() {
6818 return "SharedUserSetting{"
6819 + Integer.toHexString(System.identityHashCode(this))
6820 + " " + name + "/" + userId + "}";
6821 }
6822 }
6823
6824 /**
6825 * Holds information about dynamic settings.
6826 */
6827 private static final class Settings {
6828 private final File mSettingsFilename;
6829 private final File mBackupSettingsFilename;
David 'Digit' Turneradd13762010-02-03 17:34:58 -08006830 private final File mPackageListFilename;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006831 private final HashMap<String, PackageSetting> mPackages =
6832 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006833 // List of replaced system applications
6834 final HashMap<String, PackageSetting> mDisabledSysPackages =
6835 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 // The user's preferred activities associated with particular intent
6838 // filters.
6839 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6840 new IntentResolver<PreferredActivity, PreferredActivity>() {
6841 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006842 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006844 out.print(prefix); out.print(
6845 Integer.toHexString(System.identityHashCode(filter)));
6846 out.print(' ');
6847 out.print(filter.mActivity.flattenToShortString());
6848 out.print(" match=0x");
6849 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006851 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006852 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006853 out.print(prefix); out.print(" ");
6854 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 }
6856 }
6857 }
6858 };
6859 private final HashMap<String, SharedUserSetting> mSharedUsers =
6860 new HashMap<String, SharedUserSetting>();
6861 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6862 private final SparseArray<Object> mOtherUserIds =
6863 new SparseArray<Object>();
6864
6865 // For reading/writing settings file.
6866 private final ArrayList<Signature> mPastSignatures =
6867 new ArrayList<Signature>();
6868
6869 // Mapping from permission names to info about them.
6870 final HashMap<String, BasePermission> mPermissions =
6871 new HashMap<String, BasePermission>();
6872
6873 // Mapping from permission tree names to info about them.
6874 final HashMap<String, BasePermission> mPermissionTrees =
6875 new HashMap<String, BasePermission>();
6876
Dianne Hackborne83cefce2010-02-04 17:38:14 -08006877 // Packages that have been uninstalled and still need their external
6878 // storage data deleted.
6879 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
6880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006881 private final StringBuilder mReadMessages = new StringBuilder();
6882
6883 private static final class PendingPackage extends PackageSettingBase {
6884 final int sharedId;
6885
6886 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006887 int sharedId, int pVersionCode, int pkgFlags) {
6888 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006889 this.sharedId = sharedId;
6890 }
6891 }
6892 private final ArrayList<PendingPackage> mPendingPackages
6893 = new ArrayList<PendingPackage>();
6894
6895 Settings() {
6896 File dataDir = Environment.getDataDirectory();
6897 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006898 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6899 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006901 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 FileUtils.setPermissions(systemDir.toString(),
6903 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6904 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6905 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006906 FileUtils.setPermissions(systemSecureDir.toString(),
6907 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6908 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6909 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006910 mSettingsFilename = new File(systemDir, "packages.xml");
6911 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
David 'Digit' Turneradd13762010-02-03 17:34:58 -08006912 mPackageListFilename = new File(systemDir, "packages.list");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 }
6914
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006915 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 SharedUserSetting sharedUser, File codePath, File resourcePath,
6917 int pkgFlags, boolean create, boolean add) {
6918 final String name = pkg.packageName;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08006919 PackageSetting p = getPackageLP(name, origPackage, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006920 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006921 return p;
6922 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006923
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006924 PackageSetting peekPackageLP(String name) {
6925 return mPackages.get(name);
6926 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 PackageSetting p = mPackages.get(name);
6928 if (p != null && p.codePath.getPath().equals(codePath)) {
6929 return p;
6930 }
6931 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006932 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006933 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 void setInstallStatus(String pkgName, int status) {
6936 PackageSetting p = mPackages.get(pkgName);
6937 if(p != null) {
6938 if(p.getInstallStatus() != status) {
6939 p.setInstallStatus(status);
6940 }
6941 }
6942 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006943
Jacek Surazski65e13172009-04-28 15:26:38 +02006944 void setInstallerPackageName(String pkgName,
6945 String installerPkgName) {
6946 PackageSetting p = mPackages.get(pkgName);
6947 if(p != null) {
6948 p.setInstallerPackageName(installerPkgName);
6949 }
6950 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006951
Jacek Surazski65e13172009-04-28 15:26:38 +02006952 String getInstallerPackageName(String pkgName) {
6953 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006954 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006955 }
6956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006957 int getInstallStatus(String pkgName) {
6958 PackageSetting p = mPackages.get(pkgName);
6959 if(p != null) {
6960 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 return -1;
6963 }
6964
6965 SharedUserSetting getSharedUserLP(String name,
6966 int pkgFlags, boolean create) {
6967 SharedUserSetting s = mSharedUsers.get(name);
6968 if (s == null) {
6969 if (!create) {
6970 return null;
6971 }
6972 s = new SharedUserSetting(name, pkgFlags);
6973 if (MULTIPLE_APPLICATION_UIDS) {
6974 s.userId = newUserIdLP(s);
6975 } else {
6976 s.userId = FIRST_APPLICATION_UID;
6977 }
6978 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6979 // < 0 means we couldn't assign a userid; fall out and return
6980 // s, which is currently null
6981 if (s.userId >= 0) {
6982 mSharedUsers.put(name, s);
6983 }
6984 }
6985
6986 return s;
6987 }
6988
6989 int disableSystemPackageLP(String name) {
6990 PackageSetting p = mPackages.get(name);
6991 if(p == null) {
6992 Log.w(TAG, "Package:"+name+" is not an installed package");
6993 return -1;
6994 }
6995 PackageSetting dp = mDisabledSysPackages.get(name);
6996 // always make sure the system package code and resource paths dont change
6997 if(dp == null) {
6998 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6999 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7000 }
7001 mDisabledSysPackages.put(name, p);
7002 }
7003 return removePackageLP(name);
7004 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 PackageSetting enableSystemPackageLP(String name) {
7007 PackageSetting p = mDisabledSysPackages.get(name);
7008 if(p == null) {
7009 Log.w(TAG, "Package:"+name+" is not disabled");
7010 return null;
7011 }
7012 // Reset flag in ApplicationInfo object
7013 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
7014 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
7015 }
7016 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007017 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007018 mDisabledSysPackages.remove(name);
7019 return ret;
7020 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007023 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 PackageSetting p = mPackages.get(name);
7025 if (p != null) {
7026 if (p.userId == uid) {
7027 return p;
7028 }
7029 reportSettingsProblem(Log.ERROR,
7030 "Adding duplicate package, keeping first: " + name);
7031 return null;
7032 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007033 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 p.userId = uid;
7035 if (addUserIdLP(uid, p, name)) {
7036 mPackages.put(name, p);
7037 return p;
7038 }
7039 return null;
7040 }
7041
7042 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
7043 SharedUserSetting s = mSharedUsers.get(name);
7044 if (s != null) {
7045 if (s.userId == uid) {
7046 return s;
7047 }
7048 reportSettingsProblem(Log.ERROR,
7049 "Adding duplicate shared user, keeping first: " + name);
7050 return null;
7051 }
7052 s = new SharedUserSetting(name, pkgFlags);
7053 s.userId = uid;
7054 if (addUserIdLP(uid, s, name)) {
7055 mSharedUsers.put(name, s);
7056 return s;
7057 }
7058 return null;
7059 }
7060
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007061 // Transfer ownership of permissions from one package to another.
7062 private void transferPermissions(String origPkg, String newPkg) {
7063 // Transfer ownership of permissions to the new package.
7064 for (int i=0; i<2; i++) {
7065 HashMap<String, BasePermission> permissions =
7066 i == 0 ? mPermissionTrees : mPermissions;
7067 for (BasePermission bp : permissions.values()) {
7068 if (origPkg.equals(bp.sourcePackage)) {
7069 if (DEBUG_UPGRADE) Log.v(TAG,
7070 "Moving permission " + bp.name
7071 + " from pkg " + bp.sourcePackage
7072 + " to " + newPkg);
7073 bp.sourcePackage = newPkg;
7074 bp.perm = null;
7075 if (bp.pendingInfo != null) {
7076 bp.sourcePackage = newPkg;
7077 }
7078 bp.uid = 0;
7079 bp.gids = null;
7080 }
7081 }
7082 }
7083 }
7084
7085 private PackageSetting getPackageLP(String name, PackageSetting origPackage,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007086 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007087 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007088 PackageSetting p = mPackages.get(name);
7089 if (p != null) {
7090 if (!p.codePath.equals(codePath)) {
7091 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007092 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007093 // This is an updated system app with versions in both system
7094 // and data partition. Just let the most recent version
7095 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007096 Log.w(TAG, "Trying to update system app code path from " +
7097 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07007098 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07007099 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07007100 reportSettingsProblem(Log.WARN,
7101 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007102 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007103 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007104 }
7105 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007106 reportSettingsProblem(Log.WARN,
7107 "Package " + name + " shared user changed from "
7108 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
7109 + " to "
7110 + (sharedUser != null ? sharedUser.name : "<nothing>")
7111 + "; replacing with new");
7112 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007113 } else {
7114 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
7115 // If what we are scanning is a system package, then
7116 // make it so, regardless of whether it was previously
7117 // installed only in the data partition.
7118 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007120 }
7121 }
7122 if (p == null) {
7123 // Create a new PackageSettings entry. this can end up here because
7124 // of code path mismatch or user id mismatch of an updated system partition
7125 if (!create) {
7126 return null;
7127 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007128 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007129 if (origPackage != null) {
7130 // We are consuming the data from an existing package.
7131 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
7132 + " is adopting original package " + origPackage.name);
7133 p.copyFrom(origPackage);
7134 p.sharedUser = origPackage.sharedUser;
7135 p.userId = origPackage.userId;
7136 p.origPackage = origPackage;
7137 transferPermissions(origPackage.name, name);
7138 // Update new package state.
7139 p.setTimeStamp(codePath.lastModified());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 } else {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007141 p.setTimeStamp(codePath.lastModified());
7142 p.sharedUser = sharedUser;
7143 if (sharedUser != null) {
7144 p.userId = sharedUser.userId;
7145 } else if (MULTIPLE_APPLICATION_UIDS) {
7146 // Clone the setting here for disabled system packages
7147 PackageSetting dis = mDisabledSysPackages.get(name);
7148 if (dis != null) {
7149 // For disabled packages a new setting is created
7150 // from the existing user id. This still has to be
7151 // added to list of user id's
7152 // Copy signatures from previous setting
7153 if (dis.signatures.mSignatures != null) {
7154 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
7155 }
7156 p.userId = dis.userId;
7157 // Clone permissions
7158 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
7159 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
7160 // Clone component info
7161 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
7162 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
7163 // Add new setting to list of user ids
7164 addUserIdLP(p.userId, p, name);
7165 } else {
7166 // Assign new user id
7167 p.userId = newUserIdLP(p);
7168 }
7169 } else {
7170 p.userId = FIRST_APPLICATION_UID;
7171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007172 }
7173 if (p.userId < 0) {
7174 reportSettingsProblem(Log.WARN,
7175 "Package " + name + " could not be assigned a valid uid");
7176 return null;
7177 }
7178 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007179 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007180 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007181 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007182 }
7183 }
7184 return p;
7185 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007186
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007187 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007188 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007189 String codePath = pkg.applicationInfo.sourceDir;
7190 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007191 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007192 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007193 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007194 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007195 p.codePath = new File(codePath);
7196 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007197 }
7198 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007199 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007200 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07007201 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007202 p.resourcePath = new File(resourcePath);
7203 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007204 }
7205 // Update version code if needed
7206 if (pkg.mVersionCode != p.versionCode) {
7207 p.versionCode = pkg.mVersionCode;
7208 }
7209 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
7210 }
7211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007212 // Utility method that adds a PackageSetting to mPackages and
7213 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007214 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007215 SharedUserSetting sharedUser) {
7216 mPackages.put(name, p);
7217 if (sharedUser != null) {
7218 if (p.sharedUser != null && p.sharedUser != sharedUser) {
7219 reportSettingsProblem(Log.ERROR,
7220 "Package " + p.name + " was user "
7221 + p.sharedUser + " but is now " + sharedUser
7222 + "; I am not changing its files so it will probably fail!");
7223 p.sharedUser.packages.remove(p);
7224 } else if (p.userId != sharedUser.userId) {
7225 reportSettingsProblem(Log.ERROR,
7226 "Package " + p.name + " was user id " + p.userId
7227 + " but is now user " + sharedUser
7228 + " with id " + sharedUser.userId
7229 + "; I am not changing its files so it will probably fail!");
7230 }
7231
7232 sharedUser.packages.add(p);
7233 p.sharedUser = sharedUser;
7234 p.userId = sharedUser.userId;
7235 }
7236 }
7237
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007238 /*
7239 * Update the shared user setting when a package using
7240 * specifying the shared user id is removed. The gids
7241 * associated with each permission of the deleted package
7242 * are removed from the shared user's gid list only if its
7243 * not in use by other permissions of packages in the
7244 * shared user setting.
7245 */
7246 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007247 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
7248 Log.i(TAG, "Trying to update info for null package. Just ignoring");
7249 return;
7250 }
7251 // No sharedUserId
7252 if (deletedPs.sharedUser == null) {
7253 return;
7254 }
7255 SharedUserSetting sus = deletedPs.sharedUser;
7256 // Update permissions
7257 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
7258 boolean used = false;
7259 if (!sus.grantedPermissions.contains (eachPerm)) {
7260 continue;
7261 }
7262 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007263 if (pkg.pkg != null &&
7264 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
7265 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 used = true;
7267 break;
7268 }
7269 }
7270 if (!used) {
7271 // can safely delete this permission from list
7272 sus.grantedPermissions.remove(eachPerm);
7273 sus.loadedPermissions.remove(eachPerm);
7274 }
7275 }
7276 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007277 int newGids[] = globalGids;
7278 for (String eachPerm : sus.grantedPermissions) {
7279 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07007280 if (bp != null) {
7281 newGids = appendInts(newGids, bp.gids);
7282 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 }
7284 sus.gids = newGids;
7285 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07007286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 private int removePackageLP(String name) {
7288 PackageSetting p = mPackages.get(name);
7289 if (p != null) {
7290 mPackages.remove(name);
7291 if (p.sharedUser != null) {
7292 p.sharedUser.packages.remove(p);
7293 if (p.sharedUser.packages.size() == 0) {
7294 mSharedUsers.remove(p.sharedUser.name);
7295 removeUserIdLP(p.sharedUser.userId);
7296 return p.sharedUser.userId;
7297 }
7298 } else {
7299 removeUserIdLP(p.userId);
7300 return p.userId;
7301 }
7302 }
7303 return -1;
7304 }
7305
7306 private boolean addUserIdLP(int uid, Object obj, Object name) {
7307 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
7308 return false;
7309 }
7310
7311 if (uid >= FIRST_APPLICATION_UID) {
7312 int N = mUserIds.size();
7313 final int index = uid - FIRST_APPLICATION_UID;
7314 while (index >= N) {
7315 mUserIds.add(null);
7316 N++;
7317 }
7318 if (mUserIds.get(index) != null) {
7319 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07007320 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 + " name=" + name);
7322 return false;
7323 }
7324 mUserIds.set(index, obj);
7325 } else {
7326 if (mOtherUserIds.get(uid) != null) {
7327 reportSettingsProblem(Log.ERROR,
7328 "Adding duplicate shared id: " + uid
7329 + " name=" + name);
7330 return false;
7331 }
7332 mOtherUserIds.put(uid, obj);
7333 }
7334 return true;
7335 }
7336
7337 public Object getUserIdLP(int uid) {
7338 if (uid >= FIRST_APPLICATION_UID) {
7339 int N = mUserIds.size();
7340 final int index = uid - FIRST_APPLICATION_UID;
7341 return index < N ? mUserIds.get(index) : null;
7342 } else {
7343 return mOtherUserIds.get(uid);
7344 }
7345 }
7346
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08007347 private Set<String> findPackagesWithFlag(int flag) {
7348 Set<String> ret = new HashSet<String>();
7349 for (PackageSetting ps : mPackages.values()) {
7350 // Has to match atleast all the flag bits set on flag
7351 if ((ps.pkgFlags & flag) == flag) {
7352 ret.add(ps.name);
7353 }
7354 }
7355 return ret;
7356 }
7357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 private void removeUserIdLP(int uid) {
7359 if (uid >= FIRST_APPLICATION_UID) {
7360 int N = mUserIds.size();
7361 final int index = uid - FIRST_APPLICATION_UID;
7362 if (index < N) mUserIds.set(index, null);
7363 } else {
7364 mOtherUserIds.remove(uid);
7365 }
7366 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 void writeLP() {
7369 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
7370
7371 // Keep the old settings around until we know the new ones have
7372 // been successfully written.
7373 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007374 // Presence of backup settings file indicates that we failed
7375 // to persist settings earlier. So preserve the older
7376 // backup for future reference since the current settings
7377 // might have been corrupted.
7378 if (!mBackupSettingsFilename.exists()) {
7379 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
7380 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
7381 return;
7382 }
7383 } else {
7384 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07007385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 }
7387
7388 mPastSignatures.clear();
7389
7390 try {
7391 FileOutputStream str = new FileOutputStream(mSettingsFilename);
7392
7393 //XmlSerializer serializer = XmlUtils.serializerInstance();
7394 XmlSerializer serializer = new FastXmlSerializer();
7395 serializer.setOutput(str, "utf-8");
7396 serializer.startDocument(null, true);
7397 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
7398
7399 serializer.startTag(null, "packages");
7400
7401 serializer.startTag(null, "permission-trees");
7402 for (BasePermission bp : mPermissionTrees.values()) {
7403 writePermission(serializer, bp);
7404 }
7405 serializer.endTag(null, "permission-trees");
7406
7407 serializer.startTag(null, "permissions");
7408 for (BasePermission bp : mPermissions.values()) {
7409 writePermission(serializer, bp);
7410 }
7411 serializer.endTag(null, "permissions");
7412
7413 for (PackageSetting pkg : mPackages.values()) {
7414 writePackage(serializer, pkg);
7415 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7418 writeDisabledSysPackage(serializer, pkg);
7419 }
7420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 serializer.startTag(null, "preferred-activities");
7422 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7423 serializer.startTag(null, "item");
7424 pa.writeToXml(serializer);
7425 serializer.endTag(null, "item");
7426 }
7427 serializer.endTag(null, "preferred-activities");
7428
7429 for (SharedUserSetting usr : mSharedUsers.values()) {
7430 serializer.startTag(null, "shared-user");
7431 serializer.attribute(null, "name", usr.name);
7432 serializer.attribute(null, "userId",
7433 Integer.toString(usr.userId));
7434 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7435 serializer.startTag(null, "perms");
7436 for (String name : usr.grantedPermissions) {
7437 serializer.startTag(null, "item");
7438 serializer.attribute(null, "name", name);
7439 serializer.endTag(null, "item");
7440 }
7441 serializer.endTag(null, "perms");
7442 serializer.endTag(null, "shared-user");
7443 }
7444
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007445 if (mPackagesToBeCleaned.size() > 0) {
7446 for (int i=0; i<mPackagesToBeCleaned.size(); i++) {
7447 serializer.startTag(null, "cleaning-package");
7448 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i));
7449 serializer.endTag(null, "cleaning-package");
7450 }
7451 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007453 serializer.endTag(null, "packages");
7454
7455 serializer.endDocument();
7456
7457 str.flush();
7458 str.close();
7459
7460 // New settings successfully written, old ones are no longer
7461 // needed.
7462 mBackupSettingsFilename.delete();
7463 FileUtils.setPermissions(mSettingsFilename.toString(),
7464 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7465 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7466 |FileUtils.S_IROTH,
7467 -1, -1);
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007468
7469 // Write package list file now, use a JournaledFile.
7470 //
7471 File tempFile = new File(mPackageListFilename.toString() + ".tmp");
7472 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
7473
7474 str = new FileOutputStream(journal.chooseForWrite());
7475 try {
7476 StringBuilder sb = new StringBuilder();
7477 for (PackageSetting pkg : mPackages.values()) {
7478 ApplicationInfo ai = pkg.pkg.applicationInfo;
7479 String dataPath = ai.dataDir;
7480 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
7481
7482 // Avoid any application that has a space in its path
7483 // or that is handled by the system.
7484 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
7485 continue;
7486
7487 // we store on each line the following information for now:
7488 //
7489 // pkgName - package name
7490 // userId - application-specific user id
7491 // debugFlag - 0 or 1 if the package is debuggable.
7492 // dataPath - path to package's data path
7493 //
7494 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
7495 //
7496 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
7497 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
7498 // system/core/run-as/run-as.c
7499 //
7500 sb.setLength(0);
7501 sb.append(ai.packageName);
7502 sb.append(" ");
7503 sb.append((int)ai.uid);
7504 sb.append(isDebug ? " 1 " : " 0 ");
7505 sb.append(dataPath);
7506 sb.append("\n");
7507 str.write(sb.toString().getBytes());
7508 }
7509 str.flush();
7510 str.close();
7511 journal.commit();
7512 }
7513 catch (Exception e) {
7514 journal.rollback();
7515 }
7516
7517 FileUtils.setPermissions(mPackageListFilename.toString(),
7518 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7519 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7520 |FileUtils.S_IROTH,
7521 -1, -1);
7522
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007523 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007524
7525 } catch(XmlPullParserException e) {
7526 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007527 } catch(java.io.IOException e) {
7528 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007529 }
David 'Digit' Turneradd13762010-02-03 17:34:58 -08007530 // Clean up partially written files
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007531 if (mSettingsFilename.exists()) {
7532 if (!mSettingsFilename.delete()) {
7533 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
7534 }
7535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 //Debug.stopMethodTracing();
7537 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007538
7539 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007540 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 serializer.startTag(null, "updated-package");
7542 serializer.attribute(null, "name", pkg.name);
7543 serializer.attribute(null, "codePath", pkg.codePathString);
7544 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007545 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007546 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7547 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7548 }
7549 if (pkg.sharedUser == null) {
7550 serializer.attribute(null, "userId",
7551 Integer.toString(pkg.userId));
7552 } else {
7553 serializer.attribute(null, "sharedUserId",
7554 Integer.toString(pkg.userId));
7555 }
7556 serializer.startTag(null, "perms");
7557 if (pkg.sharedUser == null) {
7558 // If this is a shared user, the permissions will
7559 // be written there. We still need to write an
7560 // empty permissions list so permissionsFixed will
7561 // be set.
7562 for (final String name : pkg.grantedPermissions) {
7563 BasePermission bp = mPermissions.get(name);
7564 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
7565 // We only need to write signature or system permissions but this wont
7566 // match the semantics of grantedPermissions. So write all permissions.
7567 serializer.startTag(null, "item");
7568 serializer.attribute(null, "name", name);
7569 serializer.endTag(null, "item");
7570 }
7571 }
7572 }
7573 serializer.endTag(null, "perms");
7574 serializer.endTag(null, "updated-package");
7575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007576
7577 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007578 throws java.io.IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 serializer.startTag(null, "package");
7580 serializer.attribute(null, "name", pkg.name);
7581 serializer.attribute(null, "codePath", pkg.codePathString);
7582 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7583 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7584 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007585 serializer.attribute(null, "flags",
7586 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007588 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007589 if (pkg.sharedUser == null) {
7590 serializer.attribute(null, "userId",
7591 Integer.toString(pkg.userId));
7592 } else {
7593 serializer.attribute(null, "sharedUserId",
7594 Integer.toString(pkg.userId));
7595 }
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007596 if (pkg.uidError) {
7597 serializer.attribute(null, "uidError", "true");
7598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
7600 serializer.attribute(null, "enabled",
7601 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
7602 ? "true" : "false");
7603 }
7604 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
7605 serializer.attribute(null, "installStatus", "false");
7606 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007607 if (pkg.installerPackageName != null) {
7608 serializer.attribute(null, "installer", pkg.installerPackageName);
7609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007610 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
7611 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
7612 serializer.startTag(null, "perms");
7613 if (pkg.sharedUser == null) {
7614 // If this is a shared user, the permissions will
7615 // be written there. We still need to write an
7616 // empty permissions list so permissionsFixed will
7617 // be set.
7618 for (final String name : pkg.grantedPermissions) {
7619 serializer.startTag(null, "item");
7620 serializer.attribute(null, "name", name);
7621 serializer.endTag(null, "item");
7622 }
7623 }
7624 serializer.endTag(null, "perms");
7625 }
7626 if (pkg.disabledComponents.size() > 0) {
7627 serializer.startTag(null, "disabled-components");
7628 for (final String name : pkg.disabledComponents) {
7629 serializer.startTag(null, "item");
7630 serializer.attribute(null, "name", name);
7631 serializer.endTag(null, "item");
7632 }
7633 serializer.endTag(null, "disabled-components");
7634 }
7635 if (pkg.enabledComponents.size() > 0) {
7636 serializer.startTag(null, "enabled-components");
7637 for (final String name : pkg.enabledComponents) {
7638 serializer.startTag(null, "item");
7639 serializer.attribute(null, "name", name);
7640 serializer.endTag(null, "item");
7641 }
7642 serializer.endTag(null, "enabled-components");
7643 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 serializer.endTag(null, "package");
7646 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 void writePermission(XmlSerializer serializer, BasePermission bp)
7649 throws XmlPullParserException, java.io.IOException {
7650 if (bp.type != BasePermission.TYPE_BUILTIN
7651 && bp.sourcePackage != null) {
7652 serializer.startTag(null, "item");
7653 serializer.attribute(null, "name", bp.name);
7654 serializer.attribute(null, "package", bp.sourcePackage);
7655 if (DEBUG_SETTINGS) Log.v(TAG,
7656 "Writing perm: name=" + bp.name + " type=" + bp.type);
7657 if (bp.type == BasePermission.TYPE_DYNAMIC) {
7658 PermissionInfo pi = bp.perm != null ? bp.perm.info
7659 : bp.pendingInfo;
7660 if (pi != null) {
7661 serializer.attribute(null, "type", "dynamic");
7662 if (pi.icon != 0) {
7663 serializer.attribute(null, "icon",
7664 Integer.toString(pi.icon));
7665 }
7666 if (pi.nonLocalizedLabel != null) {
7667 serializer.attribute(null, "label",
7668 pi.nonLocalizedLabel.toString());
7669 }
7670 if (pi.protectionLevel !=
7671 PermissionInfo.PROTECTION_NORMAL) {
7672 serializer.attribute(null, "protection",
7673 Integer.toString(pi.protectionLevel));
7674 }
7675 }
7676 }
7677 serializer.endTag(null, "item");
7678 }
7679 }
7680
7681 String getReadMessagesLP() {
7682 return mReadMessages.toString();
7683 }
7684
Oscar Montemayora8529f62009-11-18 10:14:20 -08007685 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007686 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
7687 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007688 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007689 while(its.hasNext()) {
7690 String key = its.next();
7691 PackageSetting ps = mPackages.get(key);
7692 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08007693 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 }
7695 }
7696 return ret;
7697 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 boolean readLP() {
7700 FileInputStream str = null;
7701 if (mBackupSettingsFilename.exists()) {
7702 try {
7703 str = new FileInputStream(mBackupSettingsFilename);
7704 mReadMessages.append("Reading from backup settings file\n");
7705 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007706 if (mSettingsFilename.exists()) {
7707 // If both the backup and settings file exist, we
7708 // ignore the settings since it might have been
7709 // corrupted.
7710 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
7711 mSettingsFilename.delete();
7712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007713 } catch (java.io.IOException e) {
7714 // We'll try for the normal settings file.
7715 }
7716 }
7717
7718 mPastSignatures.clear();
7719
7720 try {
7721 if (str == null) {
7722 if (!mSettingsFilename.exists()) {
7723 mReadMessages.append("No settings file found\n");
7724 Log.i(TAG, "No current settings file!");
7725 return false;
7726 }
7727 str = new FileInputStream(mSettingsFilename);
7728 }
7729 XmlPullParser parser = Xml.newPullParser();
7730 parser.setInput(str, null);
7731
7732 int type;
7733 while ((type=parser.next()) != XmlPullParser.START_TAG
7734 && type != XmlPullParser.END_DOCUMENT) {
7735 ;
7736 }
7737
7738 if (type != XmlPullParser.START_TAG) {
7739 mReadMessages.append("No start tag found in settings file\n");
7740 Log.e(TAG, "No start tag found in package manager settings");
7741 return false;
7742 }
7743
7744 int outerDepth = parser.getDepth();
7745 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7746 && (type != XmlPullParser.END_TAG
7747 || parser.getDepth() > outerDepth)) {
7748 if (type == XmlPullParser.END_TAG
7749 || type == XmlPullParser.TEXT) {
7750 continue;
7751 }
7752
7753 String tagName = parser.getName();
7754 if (tagName.equals("package")) {
7755 readPackageLP(parser);
7756 } else if (tagName.equals("permissions")) {
7757 readPermissionsLP(mPermissions, parser);
7758 } else if (tagName.equals("permission-trees")) {
7759 readPermissionsLP(mPermissionTrees, parser);
7760 } else if (tagName.equals("shared-user")) {
7761 readSharedUserLP(parser);
7762 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007763 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007764 } else if (tagName.equals("preferred-activities")) {
7765 readPreferredActivitiesLP(parser);
7766 } else if(tagName.equals("updated-package")) {
7767 readDisabledSysPackageLP(parser);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007768 } else if (tagName.equals("cleaning-package")) {
7769 String name = parser.getAttributeValue(null, "name");
7770 if (name != null) {
7771 mPackagesToBeCleaned.add(name);
7772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007773 } else {
7774 Log.w(TAG, "Unknown element under <packages>: "
7775 + parser.getName());
7776 XmlUtils.skipCurrentTag(parser);
7777 }
7778 }
7779
7780 str.close();
7781
7782 } catch(XmlPullParserException e) {
7783 mReadMessages.append("Error reading: " + e.toString());
7784 Log.e(TAG, "Error reading package manager settings", e);
7785
7786 } catch(java.io.IOException e) {
7787 mReadMessages.append("Error reading: " + e.toString());
7788 Log.e(TAG, "Error reading package manager settings", e);
7789
7790 }
7791
7792 int N = mPendingPackages.size();
7793 for (int i=0; i<N; i++) {
7794 final PendingPackage pp = mPendingPackages.get(i);
7795 Object idObj = getUserIdLP(pp.sharedId);
7796 if (idObj != null && idObj instanceof SharedUserSetting) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007797 PackageSetting p = getPackageLP(pp.name, null,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007799 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007800 if (p == null) {
7801 Log.w(TAG, "Unable to create application package for "
7802 + pp.name);
7803 continue;
7804 }
7805 p.copyFrom(pp);
7806 } else if (idObj != null) {
7807 String msg = "Bad package setting: package " + pp.name
7808 + " has shared uid " + pp.sharedId
7809 + " that is not a shared uid\n";
7810 mReadMessages.append(msg);
7811 Log.e(TAG, msg);
7812 } else {
7813 String msg = "Bad package setting: package " + pp.name
7814 + " has shared uid " + pp.sharedId
7815 + " that is not defined\n";
7816 mReadMessages.append(msg);
7817 Log.e(TAG, msg);
7818 }
7819 }
7820 mPendingPackages.clear();
7821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822 mReadMessages.append("Read completed successfully: "
7823 + mPackages.size() + " packages, "
7824 + mSharedUsers.size() + " shared uids\n");
7825
7826 return true;
7827 }
7828
7829 private int readInt(XmlPullParser parser, String ns, String name,
7830 int defValue) {
7831 String v = parser.getAttributeValue(ns, name);
7832 try {
7833 if (v == null) {
7834 return defValue;
7835 }
7836 return Integer.parseInt(v);
7837 } catch (NumberFormatException e) {
7838 reportSettingsProblem(Log.WARN,
7839 "Error in package manager settings: attribute " +
7840 name + " has bad integer value " + v + " at "
7841 + parser.getPositionDescription());
7842 }
7843 return defValue;
7844 }
7845
7846 private void readPermissionsLP(HashMap<String, BasePermission> out,
7847 XmlPullParser parser)
7848 throws IOException, XmlPullParserException {
7849 int outerDepth = parser.getDepth();
7850 int type;
7851 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7852 && (type != XmlPullParser.END_TAG
7853 || parser.getDepth() > outerDepth)) {
7854 if (type == XmlPullParser.END_TAG
7855 || type == XmlPullParser.TEXT) {
7856 continue;
7857 }
7858
7859 String tagName = parser.getName();
7860 if (tagName.equals("item")) {
7861 String name = parser.getAttributeValue(null, "name");
7862 String sourcePackage = parser.getAttributeValue(null, "package");
7863 String ptype = parser.getAttributeValue(null, "type");
7864 if (name != null && sourcePackage != null) {
7865 boolean dynamic = "dynamic".equals(ptype);
7866 BasePermission bp = new BasePermission(name, sourcePackage,
7867 dynamic
7868 ? BasePermission.TYPE_DYNAMIC
7869 : BasePermission.TYPE_NORMAL);
7870 if (dynamic) {
7871 PermissionInfo pi = new PermissionInfo();
7872 pi.packageName = sourcePackage.intern();
7873 pi.name = name.intern();
7874 pi.icon = readInt(parser, null, "icon", 0);
7875 pi.nonLocalizedLabel = parser.getAttributeValue(
7876 null, "label");
7877 pi.protectionLevel = readInt(parser, null, "protection",
7878 PermissionInfo.PROTECTION_NORMAL);
7879 bp.pendingInfo = pi;
7880 }
7881 out.put(bp.name, bp);
7882 } else {
7883 reportSettingsProblem(Log.WARN,
7884 "Error in package manager settings: permissions has"
7885 + " no name at " + parser.getPositionDescription());
7886 }
7887 } else {
7888 reportSettingsProblem(Log.WARN,
7889 "Unknown element reading permissions: "
7890 + parser.getName() + " at "
7891 + parser.getPositionDescription());
7892 }
7893 XmlUtils.skipCurrentTag(parser);
7894 }
7895 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 private void readDisabledSysPackageLP(XmlPullParser parser)
Dianne Hackborne83cefce2010-02-04 17:38:14 -08007898 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007899 String name = parser.getAttributeValue(null, "name");
7900 String codePathStr = parser.getAttributeValue(null, "codePath");
7901 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
7902 if(resourcePathStr == null) {
7903 resourcePathStr = codePathStr;
7904 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007905 String version = parser.getAttributeValue(null, "version");
7906 int versionCode = 0;
7907 if (version != null) {
7908 try {
7909 versionCode = Integer.parseInt(version);
7910 } catch (NumberFormatException e) {
7911 }
7912 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 int pkgFlags = 0;
7915 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007916 PackageSetting ps = new PackageSetting(name,
7917 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007918 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007919 String timeStampStr = parser.getAttributeValue(null, "ts");
7920 if (timeStampStr != null) {
7921 try {
7922 long timeStamp = Long.parseLong(timeStampStr);
7923 ps.setTimeStamp(timeStamp, timeStampStr);
7924 } catch (NumberFormatException e) {
7925 }
7926 }
7927 String idStr = parser.getAttributeValue(null, "userId");
7928 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7929 if(ps.userId <= 0) {
7930 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7931 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7932 }
7933 int outerDepth = parser.getDepth();
7934 int type;
7935 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7936 && (type != XmlPullParser.END_TAG
7937 || parser.getDepth() > outerDepth)) {
7938 if (type == XmlPullParser.END_TAG
7939 || type == XmlPullParser.TEXT) {
7940 continue;
7941 }
7942
7943 String tagName = parser.getName();
7944 if (tagName.equals("perms")) {
7945 readGrantedPermissionsLP(parser,
7946 ps.grantedPermissions);
7947 } else {
7948 reportSettingsProblem(Log.WARN,
7949 "Unknown element under <updated-package>: "
7950 + parser.getName());
7951 XmlUtils.skipCurrentTag(parser);
7952 }
7953 }
7954 mDisabledSysPackages.put(name, ps);
7955 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 private void readPackageLP(XmlPullParser parser)
7958 throws XmlPullParserException, IOException {
7959 String name = null;
7960 String idStr = null;
7961 String sharedIdStr = null;
7962 String codePathStr = null;
7963 String resourcePathStr = null;
7964 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007965 String installerPackageName = null;
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007966 String uidError = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 int pkgFlags = 0;
7968 String timeStampStr;
7969 long timeStamp = 0;
7970 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007971 String version = null;
7972 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 try {
7974 name = parser.getAttributeValue(null, "name");
7975 idStr = parser.getAttributeValue(null, "userId");
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08007976 uidError = parser.getAttributeValue(null, "uidError");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7978 codePathStr = parser.getAttributeValue(null, "codePath");
7979 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007980 version = parser.getAttributeValue(null, "version");
7981 if (version != null) {
7982 try {
7983 versionCode = Integer.parseInt(version);
7984 } catch (NumberFormatException e) {
7985 }
7986 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007987 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007988
7989 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007990 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007991 try {
7992 pkgFlags = Integer.parseInt(systemStr);
7993 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007994 }
7995 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007996 // For backward compatibility
7997 systemStr = parser.getAttributeValue(null, "system");
7998 if (systemStr != null) {
7999 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
8000 } else {
8001 // Old settings that don't specify system... just treat
8002 // them as system, good enough.
8003 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008005 }
8006 timeStampStr = parser.getAttributeValue(null, "ts");
8007 if (timeStampStr != null) {
8008 try {
8009 timeStamp = Long.parseLong(timeStampStr);
8010 } catch (NumberFormatException e) {
8011 }
8012 }
8013 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
8014 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
8015 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8016 if (resourcePathStr == null) {
8017 resourcePathStr = codePathStr;
8018 }
8019 if (name == null) {
8020 reportSettingsProblem(Log.WARN,
8021 "Error in package manager settings: <package> has no name at "
8022 + parser.getPositionDescription());
8023 } else if (codePathStr == null) {
8024 reportSettingsProblem(Log.WARN,
8025 "Error in package manager settings: <package> has no codePath at "
8026 + parser.getPositionDescription());
8027 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008028 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008029 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8031 + ": userId=" + userId + " pkg=" + packageSetting);
8032 if (packageSetting == null) {
8033 reportSettingsProblem(Log.ERROR,
8034 "Failure adding uid " + userId
8035 + " while parsing settings at "
8036 + parser.getPositionDescription());
8037 } else {
8038 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8039 }
8040 } else if (sharedIdStr != null) {
8041 userId = sharedIdStr != null
8042 ? Integer.parseInt(sharedIdStr) : 0;
8043 if (userId > 0) {
8044 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07008045 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008046 packageSetting.setTimeStamp(timeStamp, timeStampStr);
8047 mPendingPackages.add((PendingPackage) packageSetting);
8048 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
8049 + ": sharedUserId=" + userId + " pkg="
8050 + packageSetting);
8051 } else {
8052 reportSettingsProblem(Log.WARN,
8053 "Error in package manager settings: package "
8054 + name + " has bad sharedId " + sharedIdStr
8055 + " at " + parser.getPositionDescription());
8056 }
8057 } else {
8058 reportSettingsProblem(Log.WARN,
8059 "Error in package manager settings: package "
8060 + name + " has bad userId " + idStr + " at "
8061 + parser.getPositionDescription());
8062 }
8063 } catch (NumberFormatException e) {
8064 reportSettingsProblem(Log.WARN,
8065 "Error in package manager settings: package "
8066 + name + " has bad userId " + idStr + " at "
8067 + parser.getPositionDescription());
8068 }
8069 if (packageSetting != null) {
Dianne Hackbornb858dfd2010-02-02 10:49:14 -08008070 packageSetting.uidError = "true".equals(uidError);
Jacek Surazski65e13172009-04-28 15:26:38 +02008071 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 final String enabledStr = parser.getAttributeValue(null, "enabled");
8073 if (enabledStr != null) {
8074 if (enabledStr.equalsIgnoreCase("true")) {
8075 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
8076 } else if (enabledStr.equalsIgnoreCase("false")) {
8077 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
8078 } else if (enabledStr.equalsIgnoreCase("default")) {
8079 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8080 } else {
8081 reportSettingsProblem(Log.WARN,
8082 "Error in package manager settings: package "
8083 + name + " has bad enabled value: " + idStr
8084 + " at " + parser.getPositionDescription());
8085 }
8086 } else {
8087 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
8088 }
8089 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
8090 if (installStatusStr != null) {
8091 if (installStatusStr.equalsIgnoreCase("false")) {
8092 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
8093 } else {
8094 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
8095 }
8096 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008098 int outerDepth = parser.getDepth();
8099 int type;
8100 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8101 && (type != XmlPullParser.END_TAG
8102 || parser.getDepth() > outerDepth)) {
8103 if (type == XmlPullParser.END_TAG
8104 || type == XmlPullParser.TEXT) {
8105 continue;
8106 }
8107
8108 String tagName = parser.getName();
8109 if (tagName.equals("disabled-components")) {
8110 readDisabledComponentsLP(packageSetting, parser);
8111 } else if (tagName.equals("enabled-components")) {
8112 readEnabledComponentsLP(packageSetting, parser);
8113 } else if (tagName.equals("sigs")) {
8114 packageSetting.signatures.readXml(parser, mPastSignatures);
8115 } else if (tagName.equals("perms")) {
8116 readGrantedPermissionsLP(parser,
8117 packageSetting.loadedPermissions);
8118 packageSetting.permissionsFixed = true;
8119 } else {
8120 reportSettingsProblem(Log.WARN,
8121 "Unknown element under <package>: "
8122 + parser.getName());
8123 XmlUtils.skipCurrentTag(parser);
8124 }
8125 }
8126 } else {
8127 XmlUtils.skipCurrentTag(parser);
8128 }
8129 }
8130
8131 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
8132 XmlPullParser parser)
8133 throws IOException, XmlPullParserException {
8134 int outerDepth = parser.getDepth();
8135 int type;
8136 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8137 && (type != XmlPullParser.END_TAG
8138 || parser.getDepth() > outerDepth)) {
8139 if (type == XmlPullParser.END_TAG
8140 || type == XmlPullParser.TEXT) {
8141 continue;
8142 }
8143
8144 String tagName = parser.getName();
8145 if (tagName.equals("item")) {
8146 String name = parser.getAttributeValue(null, "name");
8147 if (name != null) {
8148 packageSetting.disabledComponents.add(name.intern());
8149 } else {
8150 reportSettingsProblem(Log.WARN,
8151 "Error in package manager settings: <disabled-components> has"
8152 + " no name at " + parser.getPositionDescription());
8153 }
8154 } else {
8155 reportSettingsProblem(Log.WARN,
8156 "Unknown element under <disabled-components>: "
8157 + parser.getName());
8158 }
8159 XmlUtils.skipCurrentTag(parser);
8160 }
8161 }
8162
8163 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
8164 XmlPullParser parser)
8165 throws IOException, XmlPullParserException {
8166 int outerDepth = parser.getDepth();
8167 int type;
8168 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8169 && (type != XmlPullParser.END_TAG
8170 || parser.getDepth() > outerDepth)) {
8171 if (type == XmlPullParser.END_TAG
8172 || type == XmlPullParser.TEXT) {
8173 continue;
8174 }
8175
8176 String tagName = parser.getName();
8177 if (tagName.equals("item")) {
8178 String name = parser.getAttributeValue(null, "name");
8179 if (name != null) {
8180 packageSetting.enabledComponents.add(name.intern());
8181 } else {
8182 reportSettingsProblem(Log.WARN,
8183 "Error in package manager settings: <enabled-components> has"
8184 + " no name at " + parser.getPositionDescription());
8185 }
8186 } else {
8187 reportSettingsProblem(Log.WARN,
8188 "Unknown element under <enabled-components>: "
8189 + parser.getName());
8190 }
8191 XmlUtils.skipCurrentTag(parser);
8192 }
8193 }
8194
8195 private void readSharedUserLP(XmlPullParser parser)
8196 throws XmlPullParserException, IOException {
8197 String name = null;
8198 String idStr = null;
8199 int pkgFlags = 0;
8200 SharedUserSetting su = null;
8201 try {
8202 name = parser.getAttributeValue(null, "name");
8203 idStr = parser.getAttributeValue(null, "userId");
8204 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
8205 if ("true".equals(parser.getAttributeValue(null, "system"))) {
8206 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
8207 }
8208 if (name == null) {
8209 reportSettingsProblem(Log.WARN,
8210 "Error in package manager settings: <shared-user> has no name at "
8211 + parser.getPositionDescription());
8212 } else if (userId == 0) {
8213 reportSettingsProblem(Log.WARN,
8214 "Error in package manager settings: shared-user "
8215 + name + " has bad userId " + idStr + " at "
8216 + parser.getPositionDescription());
8217 } else {
8218 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
8219 reportSettingsProblem(Log.ERROR,
8220 "Occurred while parsing settings at "
8221 + parser.getPositionDescription());
8222 }
8223 }
8224 } catch (NumberFormatException e) {
8225 reportSettingsProblem(Log.WARN,
8226 "Error in package manager settings: package "
8227 + name + " has bad userId " + idStr + " at "
8228 + parser.getPositionDescription());
8229 };
8230
8231 if (su != null) {
8232 int outerDepth = parser.getDepth();
8233 int type;
8234 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8235 && (type != XmlPullParser.END_TAG
8236 || parser.getDepth() > outerDepth)) {
8237 if (type == XmlPullParser.END_TAG
8238 || type == XmlPullParser.TEXT) {
8239 continue;
8240 }
8241
8242 String tagName = parser.getName();
8243 if (tagName.equals("sigs")) {
8244 su.signatures.readXml(parser, mPastSignatures);
8245 } else if (tagName.equals("perms")) {
8246 readGrantedPermissionsLP(parser, su.loadedPermissions);
8247 } else {
8248 reportSettingsProblem(Log.WARN,
8249 "Unknown element under <shared-user>: "
8250 + parser.getName());
8251 XmlUtils.skipCurrentTag(parser);
8252 }
8253 }
8254
8255 } else {
8256 XmlUtils.skipCurrentTag(parser);
8257 }
8258 }
8259
8260 private void readGrantedPermissionsLP(XmlPullParser parser,
8261 HashSet<String> outPerms) throws IOException, XmlPullParserException {
8262 int outerDepth = parser.getDepth();
8263 int type;
8264 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8265 && (type != XmlPullParser.END_TAG
8266 || parser.getDepth() > outerDepth)) {
8267 if (type == XmlPullParser.END_TAG
8268 || type == XmlPullParser.TEXT) {
8269 continue;
8270 }
8271
8272 String tagName = parser.getName();
8273 if (tagName.equals("item")) {
8274 String name = parser.getAttributeValue(null, "name");
8275 if (name != null) {
8276 outPerms.add(name.intern());
8277 } else {
8278 reportSettingsProblem(Log.WARN,
8279 "Error in package manager settings: <perms> has"
8280 + " no name at " + parser.getPositionDescription());
8281 }
8282 } else {
8283 reportSettingsProblem(Log.WARN,
8284 "Unknown element under <perms>: "
8285 + parser.getName());
8286 }
8287 XmlUtils.skipCurrentTag(parser);
8288 }
8289 }
8290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008291 private void readPreferredActivitiesLP(XmlPullParser parser)
8292 throws XmlPullParserException, IOException {
8293 int outerDepth = parser.getDepth();
8294 int type;
8295 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
8296 && (type != XmlPullParser.END_TAG
8297 || parser.getDepth() > outerDepth)) {
8298 if (type == XmlPullParser.END_TAG
8299 || type == XmlPullParser.TEXT) {
8300 continue;
8301 }
8302
8303 String tagName = parser.getName();
8304 if (tagName.equals("item")) {
8305 PreferredActivity pa = new PreferredActivity(parser);
8306 if (pa.mParseError == null) {
8307 mPreferredActivities.addFilter(pa);
8308 } else {
8309 reportSettingsProblem(Log.WARN,
8310 "Error in package manager settings: <preferred-activity> "
8311 + pa.mParseError + " at "
8312 + parser.getPositionDescription());
8313 }
8314 } else {
8315 reportSettingsProblem(Log.WARN,
8316 "Unknown element under <preferred-activities>: "
8317 + parser.getName());
8318 XmlUtils.skipCurrentTag(parser);
8319 }
8320 }
8321 }
8322
8323 // Returns -1 if we could not find an available UserId to assign
8324 private int newUserIdLP(Object obj) {
8325 // Let's be stupidly inefficient for now...
8326 final int N = mUserIds.size();
8327 for (int i=0; i<N; i++) {
8328 if (mUserIds.get(i) == null) {
8329 mUserIds.set(i, obj);
8330 return FIRST_APPLICATION_UID + i;
8331 }
8332 }
8333
8334 // None left?
8335 if (N >= MAX_APPLICATION_UIDS) {
8336 return -1;
8337 }
8338
8339 mUserIds.add(obj);
8340 return FIRST_APPLICATION_UID + N;
8341 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008343 public PackageSetting getDisabledSystemPkg(String name) {
8344 synchronized(mPackages) {
8345 PackageSetting ps = mDisabledSysPackages.get(name);
8346 return ps;
8347 }
8348 }
8349
8350 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
8351 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
8352 if (Config.LOGV) {
8353 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
8354 + " componentName = " + componentInfo.name);
8355 Log.v(TAG, "enabledComponents: "
8356 + Arrays.toString(packageSettings.enabledComponents.toArray()));
8357 Log.v(TAG, "disabledComponents: "
8358 + Arrays.toString(packageSettings.disabledComponents.toArray()));
8359 }
8360 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
8361 || ((componentInfo.enabled
8362 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
8363 || (componentInfo.applicationInfo.enabled
8364 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
8365 && !packageSettings.disabledComponents.contains(componentInfo.name))
8366 || packageSettings.enabledComponents.contains(componentInfo.name));
8367 }
8368 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008369
8370 // ------- apps on sdcard specific code -------
8371 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08008372 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08008373 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008374 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008375 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008376
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008377
8378 static MountService getMountService() {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008379 return (MountService) ServiceManager.getService("mount");
8380 }
8381
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008382 private String getEncryptKey() {
8383 try {
8384 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8385 if (sdEncKey == null) {
8386 sdEncKey = SystemKeyStore.getInstance().
8387 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
8388 if (sdEncKey == null) {
8389 Log.e(TAG, "Failed to create encryption keys");
8390 return null;
8391 }
8392 }
8393 return sdEncKey;
8394 } catch (NoSuchAlgorithmException nsae) {
8395 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
8396 return null;
8397 }
8398 }
8399
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008400 private String createSdDir(File tmpPackageFile, String pkgName) {
8401 // Create mount point via MountService
8402 MountService mountService = getMountService();
8403 long len = tmpPackageFile.length();
8404 int mbLen = (int) (len/(1024*1024));
8405 if ((len - (mbLen * 1024 * 1024)) > 0) {
8406 mbLen++;
8407 }
8408 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
8409 String cachePath = null;
Oscar Montemayord02546b2010-01-14 16:38:40 -08008410 String sdEncKey;
8411 try {
8412 sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8413 if (sdEncKey == null) {
8414 sdEncKey = SystemKeyStore.getInstance().
8415 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
8416 if (sdEncKey == null) {
8417 Log.e(TAG, "Failed to create encryption keys for package: " + pkgName + ".");
8418 return null;
8419 }
8420 }
8421 } catch (NoSuchAlgorithmException nsae) {
8422 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
8423 return null;
8424 }
San Mehatbe16cb12010-01-29 05:35:35 -08008425
8426 int rc = mountService.createSecureContainer(
8427 pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
San Mehatb1043402010-02-05 08:26:50 -08008428 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008429 Log.e(TAG, String.format("Failed to create container (%d)", rc));
8430
8431 rc = mountService.destroySecureContainer(pkgName);
San Mehatb1043402010-02-05 08:26:50 -08008432 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008433 Log.e(TAG, String.format("Failed to cleanup container (%d)", rc));
8434 return null;
8435 }
8436 rc = mountService.createSecureContainer(
8437 pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
San Mehatb1043402010-02-05 08:26:50 -08008438 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008439 Log.e(TAG, String.format("Failed to create container (2nd try) (%d)", rc));
8440 return null;
8441 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008442 }
San Mehatbe16cb12010-01-29 05:35:35 -08008443
8444 cachePath = mountService.getSecureContainerPath(pkgName);
8445 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008446 return cachePath;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008447 }
8448
8449 private String mountSdDir(String pkgName, int ownerUid) {
Oscar Montemayord02546b2010-01-14 16:38:40 -08008450 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
8451 if (sdEncKey == null) {
8452 Log.e(TAG, "Failed to retrieve encryption keys to mount package code: " + pkgName + ".");
8453 return null;
8454 }
San Mehatbe16cb12010-01-29 05:35:35 -08008455
8456 int rc = getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
8457
San Mehatb1043402010-02-05 08:26:50 -08008458 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008459 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " rc : " + rc);
8460 return null;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008461 }
San Mehatbe16cb12010-01-29 05:35:35 -08008462
8463 return getMountService().getSecureContainerPath(pkgName);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008464 }
8465
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008466 private boolean unMountSdDir(String pkgName) {
8467 // STOPSHIP unmount directory
San Mehatbe16cb12010-01-29 05:35:35 -08008468 int rc = getMountService().unmountSecureContainer(pkgName);
San Mehatb1043402010-02-05 08:26:50 -08008469 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008470 Log.e(TAG, "Failed to unmount : " + pkgName + " with rc " + rc);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008471 return false;
8472 }
San Mehatbe16cb12010-01-29 05:35:35 -08008473 return true;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008474 }
8475
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008476 private boolean renameSdDir(String oldId, String newId) {
8477 try {
8478 getMountService().renameSecureContainer(oldId, newId);
8479 return true;
8480 } catch (IllegalStateException e) {
8481 Log.i(TAG, "Failed ot rename " + oldId + " to " + newId +
8482 " with exception : " + e);
8483 }
8484 return false;
8485 }
8486
8487 private String getSdDir(String pkgName) {
8488 return getMountService().getSecureContainerPath(pkgName);
8489 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008490
San Mehatbe16cb12010-01-29 05:35:35 -08008491 private boolean finalizeSdDir(String pkgName) {
8492 int rc = getMountService().finalizeSecureContainer(pkgName);
San Mehatb1043402010-02-05 08:26:50 -08008493 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008494 Log.i(TAG, "Failed to finalize container for pkg : " + pkgName);
8495 return false;
8496 }
8497 return true;
8498 }
8499
8500 private boolean destroySdDir(String pkgName) {
8501 int rc = getMountService().destroySecureContainer(pkgName);
San Mehatb1043402010-02-05 08:26:50 -08008502 if (rc != StorageResultCode.OperationSucceeded) {
San Mehatbe16cb12010-01-29 05:35:35 -08008503 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
8504 return false;
8505 }
8506 return true;
8507 }
8508
8509 static String[] getSecureContainerList() {
8510 String[] list = getMountService().getSecureContainerList();
8511 return list.length == 0 ? null : list;
8512 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008513
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008514 static boolean isContainerMounted(String cid) {
8515 // STOPSHIP
8516 // New api from MountService
8517 try {
8518 return (getMountService().getSecureContainerPath(cid) != null);
8519 } catch (IllegalStateException e) {
8520 }
8521 return false;
8522 }
8523
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008524 static String getTempContainerId() {
8525 String prefix = "smdl1tmp";
8526 int tmpIdx = 1;
8527 String list[] = getSecureContainerList();
8528 if (list != null) {
8529 int idx = 0;
8530 int idList[] = new int[MAX_CONTAINERS];
8531 boolean neverFound = true;
8532 for (String name : list) {
8533 // Ignore null entries
8534 if (name == null) {
8535 continue;
8536 }
8537 int sidx = name.indexOf(prefix);
8538 if (sidx == -1) {
8539 // Not a temp file. just ignore
8540 continue;
8541 }
8542 String subStr = name.substring(sidx + prefix.length());
8543 idList[idx] = -1;
8544 if (subStr != null) {
8545 try {
8546 int cid = Integer.parseInt(subStr);
8547 idList[idx++] = cid;
8548 neverFound = false;
8549 } catch (NumberFormatException e) {
8550 }
8551 }
8552 }
8553 if (!neverFound) {
8554 // Sort idList
8555 Arrays.sort(idList);
8556 for (int j = 1; j <= idList.length; j++) {
8557 if (idList[j-1] != j) {
8558 tmpIdx = j;
8559 break;
8560 }
8561 }
8562 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008563 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008564 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008565 }
8566
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008567 public void updateExternalMediaStatus(final boolean mediaStatus) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008568 synchronized (mPackages) {
8569 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
8570 mediaStatus+", mMediaMounted=" + mMediaMounted);
8571 if (mediaStatus == mMediaMounted) {
8572 return;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008573 }
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008574 mMediaMounted = mediaStatus;
8575 // Queue up an async operation since the package installation may take a little while.
8576 mHandler.post(new Runnable() {
8577 public void run() {
8578 mHandler.removeCallbacks(this);
8579 updateExternalMediaStatusInner(mediaStatus);
8580 }
8581 });
8582 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008583 }
8584
8585 void updateExternalMediaStatusInner(boolean mediaStatus) {
8586 final String list[] = getSecureContainerList();
8587 if (list == null || list.length == 0) {
8588 return;
8589 }
8590 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
8591 int uidList[] = new int[list.length];
8592 int num = 0;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008593 synchronized (mPackages) {
8594 Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
8595 for (String cid : list) {
8596 SdInstallArgs args = new SdInstallArgs(cid);
8597 String removeEntry = null;
8598 for (String app : appList) {
8599 if (args.matchContainer(app)) {
8600 removeEntry = app;
8601 break;
8602 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008603 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008604 if (removeEntry == null) {
8605 // No matching app on device. Skip entry or may be cleanup?
8606 // Ignore default package
8607 continue;
8608 }
8609 appList.remove(removeEntry);
8610 PackageSetting ps = mSettings.mPackages.get(removeEntry);
8611 processCids.put(args, ps.codePathString);
8612 int uid = ps.userId;
8613 if (uid != -1) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008614 uidList[num++] = uid;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008615 }
8616 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008617 }
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008618 int uidArr[] = null;
8619 if (num > 0) {
8620 // Sort uid list
8621 Arrays.sort(uidList, 0, num);
8622 // Throw away duplicates
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008623 uidArr = new int[num];
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008624 uidArr[0] = uidList[0];
8625 int di = 0;
8626 for (int i = 1; i < num; i++) {
8627 if (uidList[i-1] != uidList[i]) {
8628 uidArr[di++] = uidList[i];
8629 }
8630 }
8631 if (true) {
8632 for (int j = 0; j < num; j++) {
8633 Log.i(TAG, "uidArr[" + j + "]=" + uidArr[j]);
8634 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008635 }
8636 }
8637 if (mediaStatus) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008638 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008639 loadMediaPackages(processCids, uidArr);
Dianne Hackborne83cefce2010-02-04 17:38:14 -08008640 startCleaningPackages();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008641 } else {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008642 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008643 unloadMediaPackages(processCids, uidArr);
8644 }
8645 }
8646
8647 private void sendResourcesChangedBroadcast(boolean mediaStatus,
8648 ArrayList<String> pkgList, int uidArr[]) {
8649 int size = pkgList.size();
8650 if (size > 0) {
8651 // Send broadcasts here
8652 Bundle extras = new Bundle();
8653 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST,
8654 pkgList.toArray(new String[size]));
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008655 if (uidArr != null) {
8656 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
8657 }
8658 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
8659 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008660 sendPackageBroadcast(action, null, extras);
8661 }
8662 }
8663
8664 void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
8665 ArrayList<String> pkgList = new ArrayList<String>();
8666 Set<SdInstallArgs> keys = processCids.keySet();
8667 for (SdInstallArgs args : keys) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008668 String codePath = processCids.get(args);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008669 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install pkg : "
8670 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008671 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) != PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008672 Log.e(TAG, "Failed to install package: " + codePath + " from sdcard");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008673 continue;
8674 }
8675 // Parse package
8676 int parseFlags = PackageParser.PARSE_CHATTY |
8677 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8678 PackageParser pp = new PackageParser(codePath);
8679 pp.setSeparateProcesses(mSeparateProcesses);
8680 final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
8681 codePath, mMetrics, parseFlags);
8682 if (pkg == null) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008683 Log.e(TAG, "Trying to install pkg : "
8684 + args.cid + " from " + args.cachePath);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008685 continue;
8686 }
8687 setApplicationInfoPaths(pkg, codePath, codePath);
8688 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
8689 synchronized (mInstallLock) {
8690 // Scan the package
8691 if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) {
8692 synchronized (mPackages) {
8693 // Grant permissions
8694 grantPermissionsLP(pkg, false);
8695 // Persist settings
8696 mSettings.writeLP();
8697 retCode = PackageManager.INSTALL_SUCCEEDED;
8698 pkgList.add(pkg.packageName);
8699 }
8700 } else {
8701 Log.i(TAG, "Failed to install package: " + pkg.packageName + " from sdcard");
8702 }
8703 }
8704 args.doPostInstall(retCode);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008705 }
8706 // Send broadcasts first
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008707 if (pkgList.size() > 0) {
8708 sendResourcesChangedBroadcast(true, pkgList, uidArr);
8709 Runtime.getRuntime().gc();
8710 // If something failed do we clean up here or next install?
8711 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008712 }
8713
8714 void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[]) {
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008715 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages");
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008716 ArrayList<String> pkgList = new ArrayList<String>();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008717 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008718 Set<SdInstallArgs> keys = processCids.keySet();
8719 for (SdInstallArgs args : keys) {
8720 String cid = args.cid;
8721 String pkgName = args.getPackageName();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008722 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008723 // Delete package internally
8724 PackageRemovedInfo outInfo = new PackageRemovedInfo();
8725 synchronized (mInstallLock) {
8726 boolean res = deletePackageLI(pkgName, false,
8727 PackageManager.DONT_DELETE_DATA, outInfo);
8728 if (res) {
8729 pkgList.add(pkgName);
8730 } else {
8731 Log.e(TAG, "Failed to delete pkg from sdcard : " + pkgName);
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008732 failedList.add(args);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008733 }
8734 }
8735 }
8736 // Send broadcasts
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008737 if (pkgList.size() > 0) {
8738 sendResourcesChangedBroadcast(false, pkgList, uidArr);
8739 Runtime.getRuntime().gc();
8740 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008741 // Do clean up. Just unmount
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08008742 for (SdInstallArgs args : failedList) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08008743 synchronized (mInstallLock) {
8744 args.doPostDeleteLI(false);
8745 }
8746 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008748}