blob: 5566979f0562801e8e3261540cb2e97226f865bb [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
19import com.android.internal.app.ResolverActivity;
Tom Taylord4a47292009-12-21 13:59:18 -080020import com.android.common.FastXmlSerializer;
21import com.android.common.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25import org.xmlpull.v1.XmlSerializer;
26
27import android.app.ActivityManagerNative;
28import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.Context;
31import android.content.Intent;
32import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070033import android.content.IntentSender;
34import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.pm.ActivityInfo;
36import android.content.pm.ApplicationInfo;
37import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070038import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.content.pm.IPackageDataObserver;
40import android.content.pm.IPackageDeleteObserver;
41import android.content.pm.IPackageInstallObserver;
42import android.content.pm.IPackageManager;
43import android.content.pm.IPackageStatsObserver;
44import android.content.pm.InstrumentationInfo;
45import android.content.pm.PackageInfo;
46import android.content.pm.PackageManager;
47import android.content.pm.PackageStats;
48import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
49import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
50import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
51import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
52import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
53import android.content.pm.PackageParser;
54import android.content.pm.PermissionInfo;
55import android.content.pm.PermissionGroupInfo;
56import android.content.pm.ProviderInfo;
57import android.content.pm.ResolveInfo;
58import android.content.pm.ServiceInfo;
59import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.net.Uri;
61import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070062import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.Bundle;
64import android.os.HandlerThread;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070065import android.os.Looper;
66import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.Parcel;
68import android.os.RemoteException;
69import android.os.Environment;
70import android.os.FileObserver;
71import android.os.FileUtils;
72import android.os.Handler;
73import android.os.ParcelFileDescriptor;
74import android.os.Process;
75import android.os.ServiceManager;
76import android.os.SystemClock;
77import android.os.SystemProperties;
78import android.util.*;
79import android.view.Display;
80import android.view.WindowManager;
81
82import java.io.File;
83import java.io.FileDescriptor;
84import java.io.FileInputStream;
85import java.io.FileNotFoundException;
86import java.io.FileOutputStream;
87import java.io.FileReader;
88import java.io.FilenameFilter;
89import java.io.IOException;
90import java.io.InputStream;
91import java.io.PrintWriter;
92import java.util.ArrayList;
93import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -070094import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import java.util.Collections;
96import java.util.Comparator;
97import java.util.Enumeration;
98import java.util.HashMap;
99import java.util.HashSet;
100import java.util.Iterator;
101import java.util.List;
102import java.util.Map;
103import java.util.Set;
104import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800105import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.zip.ZipFile;
107import java.util.zip.ZipOutputStream;
108
109class PackageManagerService extends IPackageManager.Stub {
110 private static final String TAG = "PackageManager";
111 private static final boolean DEBUG_SETTINGS = false;
112 private static final boolean DEBUG_PREFERRED = false;
113
114 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
115 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400116 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private static final int FIRST_APPLICATION_UID =
118 Process.FIRST_APPLICATION_UID;
119 private static final int MAX_APPLICATION_UIDS = 1000;
120
121 private static final boolean SHOW_INFO = false;
122
123 private static final boolean GET_CERTIFICATES = true;
124
Oscar Montemayora8529f62009-11-18 10:14:20 -0800125 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private static final int REMOVE_EVENTS =
128 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
129 private static final int ADD_EVENTS =
130 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
131
132 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
133
134 static final int SCAN_MONITOR = 1<<0;
135 static final int SCAN_NO_DEX = 1<<1;
136 static final int SCAN_FORCE_DEX = 1<<2;
137 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800138 static final int SCAN_NEW_INSTALL = 1<<4;
139 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
142 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700143 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn851a5412009-05-08 12:06:44 -0700145 final int mSdkVersion = Build.VERSION.SDK_INT;
146 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
147 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 final Context mContext;
150 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700151 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 final DisplayMetrics mMetrics;
153 final int mDefParseFlags;
154 final String[] mSeparateProcesses;
155
156 // This is where all application persistent data goes.
157 final File mAppDataDir;
158
Oscar Montemayora8529f62009-11-18 10:14:20 -0800159 // If Encrypted File System feature is enabled, all application persistent data
160 // should go here instead.
161 final File mSecureAppDataDir;
162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 // This is the object monitoring the framework dir.
164 final FileObserver mFrameworkInstallObserver;
165
166 // This is the object monitoring the system app dir.
167 final FileObserver mSystemInstallObserver;
168
169 // This is the object monitoring mAppInstallDir.
170 final FileObserver mAppInstallObserver;
171
172 // This is the object monitoring mDrmAppPrivateInstallDir.
173 final FileObserver mDrmAppInstallObserver;
174
175 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
176 // LOCK HELD. Can be called with mInstallLock held.
177 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 final File mFrameworkDir;
180 final File mSystemAppDir;
181 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700182 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183
184 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
185 // apps.
186 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // Lock for state used when installing and doing other long running
191 // operations. Methods that must be called with this lock held have
192 // the prefix "LI".
193 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 // These are the directories in the 3rd party applications installed dir
196 // that we have currently loaded packages from. Keys are the application's
197 // installed zip file (absolute codePath), and values are Package.
198 final HashMap<String, PackageParser.Package> mAppDirs =
199 new HashMap<String, PackageParser.Package>();
200
201 // Information for the parser to write more useful error messages.
202 File mScanningPath;
203 int mLastScanError;
204
205 final int[] mOutPermissions = new int[3];
206
207 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // Keys are String (package name), values are Package. This also serves
210 // as the lock for the global state. Methods that must be called with
211 // this lock held have the prefix "LP".
212 final HashMap<String, PackageParser.Package> mPackages =
213 new HashMap<String, PackageParser.Package>();
214
215 final Settings mSettings;
216 boolean mRestoredSettings;
217 boolean mReportedUidError;
218
219 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
220 int[] mGlobalGids;
221
222 // These are the built-in uid -> permission mappings that were read from the
223 // etc/permissions.xml file.
224 final SparseArray<HashSet<String>> mSystemPermissions =
225 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 // These are the built-in shared libraries that were read from the
228 // etc/permissions.xml file.
229 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800230
Dianne Hackborn49237342009-08-27 20:08:01 -0700231 // Temporary for building the final shared libraries for an .apk.
232 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800233
Dianne Hackborn49237342009-08-27 20:08:01 -0700234 // These are the features this devices supports that were read from the
235 // etc/permissions.xml file.
236 final HashMap<String, FeatureInfo> mAvailableFeatures =
237 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // All available activities, for your resolving pleasure.
240 final ActivityIntentResolver mActivities =
241 new ActivityIntentResolver();
242
243 // All available receivers, for your resolving pleasure.
244 final ActivityIntentResolver mReceivers =
245 new ActivityIntentResolver();
246
247 // All available services, for your resolving pleasure.
248 final ServiceIntentResolver mServices = new ServiceIntentResolver();
249
250 // Keys are String (provider class name), values are Provider.
251 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
252 new HashMap<ComponentName, PackageParser.Provider>();
253
254 // Mapping from provider base names (first directory in content URI codePath)
255 // to the provider information.
256 final HashMap<String, PackageParser.Provider> mProviders =
257 new HashMap<String, PackageParser.Provider>();
258
259 // Mapping from instrumentation class names to info about them.
260 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
261 new HashMap<ComponentName, PackageParser.Instrumentation>();
262
263 // Mapping from permission names to info about them.
264 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
265 new HashMap<String, PackageParser.PermissionGroup>();
266
Dianne Hackborn854060af2009-07-09 18:14:31 -0700267 // Broadcast actions that are only available to the system.
268 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 boolean mSystemReady;
271 boolean mSafeMode;
272 boolean mHasSystemUidErrors;
273
274 ApplicationInfo mAndroidApplication;
275 final ActivityInfo mResolveActivity = new ActivityInfo();
276 final ResolveInfo mResolveInfo = new ResolveInfo();
277 ComponentName mResolveComponentName;
278 PackageParser.Package mPlatformPackage;
279
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700280 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800281 final HashMap<String, ArrayList<String>> mPendingBroadcasts
282 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700283 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800284 static final int DESTROY_SD_CONTAINER = 2;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700285 // Delay time in millisecs
286 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800287 static final int DESTROY_SD_CONTAINER_DELAY = 30 * 1000;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700288
289 class PackageHandler extends Handler {
290 PackageHandler(Looper looper) {
291 super(looper);
292 }
293 public void handleMessage(Message msg) {
294 switch (msg.what) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800295 case DESTROY_SD_CONTAINER:
296 String pkgName = (String) msg.obj;
297 if (pkgName != null) {
298 // Too bad we cannot handle the errors from destroying the containers.
299 if (!destroySdDir(pkgName)) {
300 Log.e(TAG, "Failed to destroy container for pkg : " + pkgName);
301 }
302 }
303 break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700304 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800305 String packages[];
306 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700307 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700308 int uids[];
309 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800310 if (mPendingBroadcasts == null) {
311 return;
312 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700313 size = mPendingBroadcasts.size();
314 if (size <= 0) {
315 // Nothing to be done. Just return
316 return;
317 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800318 packages = new String[size];
319 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700320 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800321 Iterator<HashMap.Entry<String, ArrayList<String>>>
322 it = mPendingBroadcasts.entrySet().iterator();
323 int i = 0;
324 while (it.hasNext() && i < size) {
325 HashMap.Entry<String, ArrayList<String>> ent = it.next();
326 packages[i] = ent.getKey();
327 components[i] = ent.getValue();
328 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700329 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800330 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700331 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800332 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700333 mPendingBroadcasts.clear();
334 }
335 // Send broadcasts
336 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800337 sendPackageChangedBroadcast(packages[i], true,
338 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700339 }
340 break;
341 }
342 }
343 }
344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 public static final IPackageManager main(Context context, boolean factoryTest) {
346 PackageManagerService m = new PackageManagerService(context, factoryTest);
347 ServiceManager.addService("package", m);
348 return m;
349 }
350
351 static String[] splitString(String str, char sep) {
352 int count = 1;
353 int i = 0;
354 while ((i=str.indexOf(sep, i)) >= 0) {
355 count++;
356 i++;
357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 String[] res = new String[count];
360 i=0;
361 count = 0;
362 int lastI=0;
363 while ((i=str.indexOf(sep, i)) >= 0) {
364 res[count] = str.substring(lastI, i);
365 count++;
366 i++;
367 lastI = i;
368 }
369 res[count] = str.substring(lastI, str.length());
370 return res;
371 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800374 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800376
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 if (mSdkVersion <= 0) {
378 Log.w(TAG, "**** ro.build.version.sdk not set!");
379 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 mContext = context;
382 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700383 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 mMetrics = new DisplayMetrics();
385 mSettings = new Settings();
386 mSettings.addSharedUserLP("android.uid.system",
387 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
388 mSettings.addSharedUserLP("android.uid.phone",
389 MULTIPLE_APPLICATION_UIDS
390 ? RADIO_UID : FIRST_APPLICATION_UID,
391 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400392 mSettings.addSharedUserLP("android.uid.log",
393 MULTIPLE_APPLICATION_UIDS
394 ? LOG_UID : FIRST_APPLICATION_UID,
395 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396
397 String separateProcesses = SystemProperties.get("debug.separate_processes");
398 if (separateProcesses != null && separateProcesses.length() > 0) {
399 if ("*".equals(separateProcesses)) {
400 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
401 mSeparateProcesses = null;
402 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
403 } else {
404 mDefParseFlags = 0;
405 mSeparateProcesses = separateProcesses.split(",");
406 Log.w(TAG, "Running with debug.separate_processes: "
407 + separateProcesses);
408 }
409 } else {
410 mDefParseFlags = 0;
411 mSeparateProcesses = null;
412 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 Installer installer = new Installer();
415 // Little hacky thing to check if installd is here, to determine
416 // whether we are running on the simulator and thus need to take
417 // care of building the /data file structure ourself.
418 // (apparently the sim now has a working installer)
419 if (installer.ping() && Process.supportsProcesses()) {
420 mInstaller = installer;
421 } else {
422 mInstaller = null;
423 }
424
425 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
426 Display d = wm.getDefaultDisplay();
427 d.getMetrics(mMetrics);
428
429 synchronized (mInstallLock) {
430 synchronized (mPackages) {
431 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700432 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 File dataDir = Environment.getDataDirectory();
435 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800436 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
438
439 if (mInstaller == null) {
440 // Make sure these dirs exist, when we are running in
441 // the simulator.
442 // Make a wide-open directory for random misc stuff.
443 File miscDir = new File(dataDir, "misc");
444 miscDir.mkdirs();
445 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800446 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 mDrmAppPrivateInstallDir.mkdirs();
448 }
449
450 readPermissions();
451
452 mRestoredSettings = mSettings.readLP();
453 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800454
455 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700459 if (mNoDexOpt) {
460 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800461 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700462 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700467 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700470 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 /**
473 * Out of paranoia, ensure that everything in the boot class
474 * path has been dexed.
475 */
476 String bootClassPath = System.getProperty("java.boot.class.path");
477 if (bootClassPath != null) {
478 String[] paths = splitString(bootClassPath, ':');
479 for (int i=0; i<paths.length; i++) {
480 try {
481 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
482 libFiles.add(paths[i]);
483 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700484 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 }
486 } catch (FileNotFoundException e) {
487 Log.w(TAG, "Boot class path not found: " + paths[i]);
488 } catch (IOException e) {
489 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
490 }
491 }
492 } else {
493 Log.w(TAG, "No BOOTCLASSPATH found!");
494 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 /**
497 * Also ensure all external libraries have had dexopt run on them.
498 */
499 if (mSharedLibraries.size() > 0) {
500 Iterator<String> libs = mSharedLibraries.values().iterator();
501 while (libs.hasNext()) {
502 String lib = libs.next();
503 try {
504 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
505 libFiles.add(lib);
506 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700507 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509 } catch (FileNotFoundException e) {
510 Log.w(TAG, "Library not found: " + lib);
511 } catch (IOException e) {
512 Log.w(TAG, "Exception reading library: " + lib, e);
513 }
514 }
515 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 // Gross hack for now: we know this file doesn't contain any
518 // code, so don't dexopt it to avoid the resulting log spew.
519 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 /**
522 * And there are a number of commands implemented in Java, which
523 * we currently need to do the dexopt on so that they can be
524 * run from a non-root shell.
525 */
526 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700527 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 for (int i=0; i<frameworkFiles.length; i++) {
529 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
530 String path = libPath.getPath();
531 // Skip the file if we alrady did it.
532 if (libFiles.contains(path)) {
533 continue;
534 }
535 // Skip the file if it is not a type we want to dexopt.
536 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
537 continue;
538 }
539 try {
540 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
541 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700542 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 }
544 } catch (FileNotFoundException e) {
545 Log.w(TAG, "Jar not found: " + path);
546 } catch (IOException e) {
547 Log.w(TAG, "Exception reading jar: " + path, e);
548 }
549 }
550 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800551
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700552 if (didDexOpt) {
553 // If we had to do a dexopt of one of the previous
554 // things, then something on the system has changed.
555 // Consider this significant, and wipe away all other
556 // existing dexopt files to ensure we don't leave any
557 // dangling around.
558 String[] files = mDalvikCacheDir.list();
559 if (files != null) {
560 for (int i=0; i<files.length; i++) {
561 String fn = files[i];
562 if (fn.startsWith("data@app@")
563 || fn.startsWith("data@app-private@")) {
564 Log.i(TAG, "Pruning dalvik file: " + fn);
565 (new File(mDalvikCacheDir, fn)).delete();
566 }
567 }
568 }
569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 mFrameworkInstallObserver = new AppDirObserver(
573 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
574 mFrameworkInstallObserver.startWatching();
575 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800576 scanMode | SCAN_NO_DEX | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
578 mSystemInstallObserver = new AppDirObserver(
579 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
580 mSystemInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800581 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 mAppInstallDir = new File(dataDir, "app");
583 if (mInstaller == null) {
584 // Make sure these dirs exist, when we are running in
585 // the simulator.
586 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
587 }
588 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800589 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 //clean up list
591 for(int i = 0; i < deletePkgsList.size(); i++) {
592 //clean up here
593 cleanupInstallFailedPackage(deletePkgsList.get(i));
594 }
595 //delete tmp files
596 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800597
598 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 SystemClock.uptimeMillis());
600 mAppInstallObserver = new AppDirObserver(
601 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
602 mAppInstallObserver.startWatching();
603 scanDirLI(mAppInstallDir, 0, scanMode);
604
605 mDrmAppInstallObserver = new AppDirObserver(
606 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
607 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800608 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800610 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 SystemClock.uptimeMillis());
612 Log.i(TAG, "Time to scan packages: "
613 + ((SystemClock.uptimeMillis()-startTime)/1000f)
614 + " seconds");
615
616 updatePermissionsLP();
617
618 mSettings.writeLP();
619
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800620 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 // Now after opening every single application zip, make sure they
624 // are all flushed. Not really needed, but keeps things nice and
625 // tidy.
626 Runtime.getRuntime().gc();
627 } // synchronized (mPackages)
628 } // synchronized (mInstallLock)
629 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 @Override
632 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
633 throws RemoteException {
634 try {
635 return super.onTransact(code, data, reply, flags);
636 } catch (RuntimeException e) {
637 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
638 Log.e(TAG, "Package Manager Crash", e);
639 }
640 throw e;
641 }
642 }
643
Oscar Montemayora8529f62009-11-18 10:14:20 -0800644 void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800646 boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
647 int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 if (retCode < 0) {
649 Log.w(TAG, "Couldn't remove app data directory for package: "
Oscar Montemayora8529f62009-11-18 10:14:20 -0800650 + pkgSettings.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 }
652 } else {
653 //for emulator
Oscar Montemayora8529f62009-11-18 10:14:20 -0800654 File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 dataDir.delete();
656 }
Oscar Montemayora8529f62009-11-18 10:14:20 -0800657 mSettings.removePackageLP(pkgSettings.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 }
659
660 void readPermissions() {
661 // Read permissions from .../etc/permission directory.
662 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
663 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
664 Log.w(TAG, "No directory " + libraryDir + ", skipping");
665 return;
666 }
667 if (!libraryDir.canRead()) {
668 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
669 return;
670 }
671
672 // Iterate over the files in the directory and scan .xml files
673 for (File f : libraryDir.listFiles()) {
674 // We'll read platform.xml last
675 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
676 continue;
677 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 if (!f.getPath().endsWith(".xml")) {
680 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
681 continue;
682 }
683 if (!f.canRead()) {
684 Log.w(TAG, "Permissions library file " + f + " cannot be read");
685 continue;
686 }
687
688 readPermissionsFromXml(f);
689 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
692 final File permFile = new File(Environment.getRootDirectory(),
693 "etc/permissions/platform.xml");
694 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800695
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700696 StringBuilder sb = new StringBuilder(128);
697 sb.append("Libs:");
698 Iterator<String> it = mSharedLibraries.keySet().iterator();
699 while (it.hasNext()) {
700 sb.append(' ');
701 String name = it.next();
702 sb.append(name);
703 sb.append(':');
704 sb.append(mSharedLibraries.get(name));
705 }
706 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800707
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700708 sb.setLength(0);
709 sb.append("Features:");
710 it = mAvailableFeatures.keySet().iterator();
711 while (it.hasNext()) {
712 sb.append(' ');
713 sb.append(it.next());
714 }
715 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800717
718 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 FileReader permReader = null;
720 try {
721 permReader = new FileReader(permFile);
722 } catch (FileNotFoundException e) {
723 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
724 return;
725 }
726
727 try {
728 XmlPullParser parser = Xml.newPullParser();
729 parser.setInput(permReader);
730
731 XmlUtils.beginDocument(parser, "permissions");
732
733 while (true) {
734 XmlUtils.nextElement(parser);
735 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
736 break;
737 }
738
739 String name = parser.getName();
740 if ("group".equals(name)) {
741 String gidStr = parser.getAttributeValue(null, "gid");
742 if (gidStr != null) {
743 int gid = Integer.parseInt(gidStr);
744 mGlobalGids = appendInt(mGlobalGids, gid);
745 } else {
746 Log.w(TAG, "<group> without gid at "
747 + parser.getPositionDescription());
748 }
749
750 XmlUtils.skipCurrentTag(parser);
751 continue;
752 } else if ("permission".equals(name)) {
753 String perm = parser.getAttributeValue(null, "name");
754 if (perm == null) {
755 Log.w(TAG, "<permission> without name at "
756 + parser.getPositionDescription());
757 XmlUtils.skipCurrentTag(parser);
758 continue;
759 }
760 perm = perm.intern();
761 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 } else if ("assign-permission".equals(name)) {
764 String perm = parser.getAttributeValue(null, "name");
765 if (perm == null) {
766 Log.w(TAG, "<assign-permission> without name at "
767 + parser.getPositionDescription());
768 XmlUtils.skipCurrentTag(parser);
769 continue;
770 }
771 String uidStr = parser.getAttributeValue(null, "uid");
772 if (uidStr == null) {
773 Log.w(TAG, "<assign-permission> without uid at "
774 + parser.getPositionDescription());
775 XmlUtils.skipCurrentTag(parser);
776 continue;
777 }
778 int uid = Process.getUidForName(uidStr);
779 if (uid < 0) {
780 Log.w(TAG, "<assign-permission> with unknown uid \""
781 + uidStr + "\" at "
782 + parser.getPositionDescription());
783 XmlUtils.skipCurrentTag(parser);
784 continue;
785 }
786 perm = perm.intern();
787 HashSet<String> perms = mSystemPermissions.get(uid);
788 if (perms == null) {
789 perms = new HashSet<String>();
790 mSystemPermissions.put(uid, perms);
791 }
792 perms.add(perm);
793 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 } else if ("library".equals(name)) {
796 String lname = parser.getAttributeValue(null, "name");
797 String lfile = parser.getAttributeValue(null, "file");
798 if (lname == null) {
799 Log.w(TAG, "<library> without name at "
800 + parser.getPositionDescription());
801 } else if (lfile == null) {
802 Log.w(TAG, "<library> without file at "
803 + parser.getPositionDescription());
804 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700805 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700806 mSharedLibraries.put(lname, lfile);
807 }
808 XmlUtils.skipCurrentTag(parser);
809 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800810
Dianne Hackborn49237342009-08-27 20:08:01 -0700811 } else if ("feature".equals(name)) {
812 String fname = parser.getAttributeValue(null, "name");
813 if (fname == null) {
814 Log.w(TAG, "<feature> without name at "
815 + parser.getPositionDescription());
816 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700817 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700818 FeatureInfo fi = new FeatureInfo();
819 fi.name = fname;
820 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
822 XmlUtils.skipCurrentTag(parser);
823 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 } else {
826 XmlUtils.skipCurrentTag(parser);
827 continue;
828 }
829
830 }
831 } catch (XmlPullParserException e) {
832 Log.w(TAG, "Got execption parsing permissions.", e);
833 } catch (IOException e) {
834 Log.w(TAG, "Got execption parsing permissions.", e);
835 }
836 }
837
838 void readPermission(XmlPullParser parser, String name)
839 throws IOException, XmlPullParserException {
840
841 name = name.intern();
842
843 BasePermission bp = mSettings.mPermissions.get(name);
844 if (bp == null) {
845 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
846 mSettings.mPermissions.put(name, bp);
847 }
848 int outerDepth = parser.getDepth();
849 int type;
850 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
851 && (type != XmlPullParser.END_TAG
852 || parser.getDepth() > outerDepth)) {
853 if (type == XmlPullParser.END_TAG
854 || type == XmlPullParser.TEXT) {
855 continue;
856 }
857
858 String tagName = parser.getName();
859 if ("group".equals(tagName)) {
860 String gidStr = parser.getAttributeValue(null, "gid");
861 if (gidStr != null) {
862 int gid = Process.getGidForName(gidStr);
863 bp.gids = appendInt(bp.gids, gid);
864 } else {
865 Log.w(TAG, "<group> without gid at "
866 + parser.getPositionDescription());
867 }
868 }
869 XmlUtils.skipCurrentTag(parser);
870 }
871 }
872
873 static int[] appendInt(int[] cur, int val) {
874 if (cur == null) {
875 return new int[] { val };
876 }
877 final int N = cur.length;
878 for (int i=0; i<N; i++) {
879 if (cur[i] == val) {
880 return cur;
881 }
882 }
883 int[] ret = new int[N+1];
884 System.arraycopy(cur, 0, ret, 0, N);
885 ret[N] = val;
886 return ret;
887 }
888
889 static int[] appendInts(int[] cur, int[] add) {
890 if (add == null) return cur;
891 if (cur == null) return add;
892 final int N = add.length;
893 for (int i=0; i<N; i++) {
894 cur = appendInt(cur, add[i]);
895 }
896 return cur;
897 }
898
899 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700900 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
901 // The package has been uninstalled but has retained data and resources.
902 return PackageParser.generatePackageInfo(p, null, flags);
903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 final PackageSetting ps = (PackageSetting)p.mExtras;
905 if (ps == null) {
906 return null;
907 }
908 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
909 return PackageParser.generatePackageInfo(p, gp.gids, flags);
910 }
911
912 public PackageInfo getPackageInfo(String packageName, int flags) {
913 synchronized (mPackages) {
914 PackageParser.Package p = mPackages.get(packageName);
915 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700916 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 + ": " + p);
918 if (p != null) {
919 return generatePackageInfo(p, flags);
920 }
921 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
922 return generatePackageInfoFromSettingsLP(packageName, flags);
923 }
924 }
925 return null;
926 }
927
928 public int getPackageUid(String packageName) {
929 synchronized (mPackages) {
930 PackageParser.Package p = mPackages.get(packageName);
931 if(p != null) {
932 return p.applicationInfo.uid;
933 }
934 PackageSetting ps = mSettings.mPackages.get(packageName);
935 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
936 return -1;
937 }
938 p = ps.pkg;
939 return p != null ? p.applicationInfo.uid : -1;
940 }
941 }
942
943 public int[] getPackageGids(String packageName) {
944 synchronized (mPackages) {
945 PackageParser.Package p = mPackages.get(packageName);
946 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700947 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 + ": " + p);
949 if (p != null) {
950 final PackageSetting ps = (PackageSetting)p.mExtras;
951 final SharedUserSetting suid = ps.sharedUser;
952 return suid != null ? suid.gids : ps.gids;
953 }
954 }
955 // stupid thing to indicate an error.
956 return new int[0];
957 }
958
959 public PermissionInfo getPermissionInfo(String name, int flags) {
960 synchronized (mPackages) {
961 final BasePermission p = mSettings.mPermissions.get(name);
962 if (p != null && p.perm != null) {
963 return PackageParser.generatePermissionInfo(p.perm, flags);
964 }
965 return null;
966 }
967 }
968
969 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
970 synchronized (mPackages) {
971 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
972 for (BasePermission p : mSettings.mPermissions.values()) {
973 if (group == null) {
974 if (p.perm.info.group == null) {
975 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
976 }
977 } else {
978 if (group.equals(p.perm.info.group)) {
979 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
980 }
981 }
982 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 if (out.size() > 0) {
985 return out;
986 }
987 return mPermissionGroups.containsKey(group) ? out : null;
988 }
989 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
992 synchronized (mPackages) {
993 return PackageParser.generatePermissionGroupInfo(
994 mPermissionGroups.get(name), flags);
995 }
996 }
997
998 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
999 synchronized (mPackages) {
1000 final int N = mPermissionGroups.size();
1001 ArrayList<PermissionGroupInfo> out
1002 = new ArrayList<PermissionGroupInfo>(N);
1003 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1004 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1005 }
1006 return out;
1007 }
1008 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1011 PackageSetting ps = mSettings.mPackages.get(packageName);
1012 if(ps != null) {
1013 if(ps.pkg == null) {
1014 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1015 if(pInfo != null) {
1016 return pInfo.applicationInfo;
1017 }
1018 return null;
1019 }
1020 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1021 }
1022 return null;
1023 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1026 PackageSetting ps = mSettings.mPackages.get(packageName);
1027 if(ps != null) {
1028 if(ps.pkg == null) {
1029 ps.pkg = new PackageParser.Package(packageName);
1030 ps.pkg.applicationInfo.packageName = packageName;
1031 }
1032 return generatePackageInfo(ps.pkg, flags);
1033 }
1034 return null;
1035 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1038 synchronized (mPackages) {
1039 PackageParser.Package p = mPackages.get(packageName);
1040 if (Config.LOGV) Log.v(
1041 TAG, "getApplicationInfo " + packageName
1042 + ": " + p);
1043 if (p != null) {
1044 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001045 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 }
1047 if ("android".equals(packageName)||"system".equals(packageName)) {
1048 return mAndroidApplication;
1049 }
1050 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1051 return generateApplicationInfoFromSettingsLP(packageName, flags);
1052 }
1053 }
1054 return null;
1055 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001056
1057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1059 mContext.enforceCallingOrSelfPermission(
1060 android.Manifest.permission.CLEAR_APP_CACHE, null);
1061 // Queue up an async operation since clearing cache may take a little while.
1062 mHandler.post(new Runnable() {
1063 public void run() {
1064 mHandler.removeCallbacks(this);
1065 int retCode = -1;
1066 if (mInstaller != null) {
1067 retCode = mInstaller.freeCache(freeStorageSize);
1068 if (retCode < 0) {
1069 Log.w(TAG, "Couldn't clear application caches");
1070 }
1071 } //end if mInstaller
1072 if (observer != null) {
1073 try {
1074 observer.onRemoveCompleted(null, (retCode >= 0));
1075 } catch (RemoteException e) {
1076 Log.w(TAG, "RemoveException when invoking call back");
1077 }
1078 }
1079 }
1080 });
1081 }
1082
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001083 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001084 mContext.enforceCallingOrSelfPermission(
1085 android.Manifest.permission.CLEAR_APP_CACHE, null);
1086 // Queue up an async operation since clearing cache may take a little while.
1087 mHandler.post(new Runnable() {
1088 public void run() {
1089 mHandler.removeCallbacks(this);
1090 int retCode = -1;
1091 if (mInstaller != null) {
1092 retCode = mInstaller.freeCache(freeStorageSize);
1093 if (retCode < 0) {
1094 Log.w(TAG, "Couldn't clear application caches");
1095 }
1096 }
1097 if(pi != null) {
1098 try {
1099 // Callback via pending intent
1100 int code = (retCode >= 0) ? 1 : 0;
1101 pi.sendIntent(null, code, null,
1102 null, null);
1103 } catch (SendIntentException e1) {
1104 Log.i(TAG, "Failed to send pending intent");
1105 }
1106 }
1107 }
1108 });
1109 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1112 synchronized (mPackages) {
1113 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001114
1115 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001117 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 }
1119 if (mResolveComponentName.equals(component)) {
1120 return mResolveActivity;
1121 }
1122 }
1123 return null;
1124 }
1125
1126 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1127 synchronized (mPackages) {
1128 PackageParser.Activity a = mReceivers.mActivities.get(component);
1129 if (Config.LOGV) Log.v(
1130 TAG, "getReceiverInfo " + component + ": " + a);
1131 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1132 return PackageParser.generateActivityInfo(a, flags);
1133 }
1134 }
1135 return null;
1136 }
1137
1138 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1139 synchronized (mPackages) {
1140 PackageParser.Service s = mServices.mServices.get(component);
1141 if (Config.LOGV) Log.v(
1142 TAG, "getServiceInfo " + component + ": " + s);
1143 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1144 return PackageParser.generateServiceInfo(s, flags);
1145 }
1146 }
1147 return null;
1148 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 public String[] getSystemSharedLibraryNames() {
1151 Set<String> libSet;
1152 synchronized (mPackages) {
1153 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001154 int size = libSet.size();
1155 if (size > 0) {
1156 String[] libs = new String[size];
1157 libSet.toArray(libs);
1158 return libs;
1159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001161 return null;
1162 }
1163
1164 public FeatureInfo[] getSystemAvailableFeatures() {
1165 Collection<FeatureInfo> featSet;
1166 synchronized (mPackages) {
1167 featSet = mAvailableFeatures.values();
1168 int size = featSet.size();
1169 if (size > 0) {
1170 FeatureInfo[] features = new FeatureInfo[size+1];
1171 featSet.toArray(features);
1172 FeatureInfo fi = new FeatureInfo();
1173 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1174 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1175 features[size] = fi;
1176 return features;
1177 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 }
1179 return null;
1180 }
1181
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001182 public boolean hasSystemFeature(String name) {
1183 synchronized (mPackages) {
1184 return mAvailableFeatures.containsKey(name);
1185 }
1186 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 public int checkPermission(String permName, String pkgName) {
1189 synchronized (mPackages) {
1190 PackageParser.Package p = mPackages.get(pkgName);
1191 if (p != null && p.mExtras != null) {
1192 PackageSetting ps = (PackageSetting)p.mExtras;
1193 if (ps.sharedUser != null) {
1194 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1195 return PackageManager.PERMISSION_GRANTED;
1196 }
1197 } else if (ps.grantedPermissions.contains(permName)) {
1198 return PackageManager.PERMISSION_GRANTED;
1199 }
1200 }
1201 }
1202 return PackageManager.PERMISSION_DENIED;
1203 }
1204
1205 public int checkUidPermission(String permName, int uid) {
1206 synchronized (mPackages) {
1207 Object obj = mSettings.getUserIdLP(uid);
1208 if (obj != null) {
1209 if (obj instanceof SharedUserSetting) {
1210 SharedUserSetting sus = (SharedUserSetting)obj;
1211 if (sus.grantedPermissions.contains(permName)) {
1212 return PackageManager.PERMISSION_GRANTED;
1213 }
1214 } else if (obj instanceof PackageSetting) {
1215 PackageSetting ps = (PackageSetting)obj;
1216 if (ps.grantedPermissions.contains(permName)) {
1217 return PackageManager.PERMISSION_GRANTED;
1218 }
1219 }
1220 } else {
1221 HashSet<String> perms = mSystemPermissions.get(uid);
1222 if (perms != null && perms.contains(permName)) {
1223 return PackageManager.PERMISSION_GRANTED;
1224 }
1225 }
1226 }
1227 return PackageManager.PERMISSION_DENIED;
1228 }
1229
1230 private BasePermission findPermissionTreeLP(String permName) {
1231 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1232 if (permName.startsWith(bp.name) &&
1233 permName.length() > bp.name.length() &&
1234 permName.charAt(bp.name.length()) == '.') {
1235 return bp;
1236 }
1237 }
1238 return null;
1239 }
1240
1241 private BasePermission checkPermissionTreeLP(String permName) {
1242 if (permName != null) {
1243 BasePermission bp = findPermissionTreeLP(permName);
1244 if (bp != null) {
1245 if (bp.uid == Binder.getCallingUid()) {
1246 return bp;
1247 }
1248 throw new SecurityException("Calling uid "
1249 + Binder.getCallingUid()
1250 + " is not allowed to add to permission tree "
1251 + bp.name + " owned by uid " + bp.uid);
1252 }
1253 }
1254 throw new SecurityException("No permission tree found for " + permName);
1255 }
1256
1257 public boolean addPermission(PermissionInfo info) {
1258 synchronized (mPackages) {
1259 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1260 throw new SecurityException("Label must be specified in permission");
1261 }
1262 BasePermission tree = checkPermissionTreeLP(info.name);
1263 BasePermission bp = mSettings.mPermissions.get(info.name);
1264 boolean added = bp == null;
1265 if (added) {
1266 bp = new BasePermission(info.name, tree.sourcePackage,
1267 BasePermission.TYPE_DYNAMIC);
1268 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1269 throw new SecurityException(
1270 "Not allowed to modify non-dynamic permission "
1271 + info.name);
1272 }
1273 bp.perm = new PackageParser.Permission(tree.perm.owner,
1274 new PermissionInfo(info));
1275 bp.perm.info.packageName = tree.perm.info.packageName;
1276 bp.uid = tree.uid;
1277 if (added) {
1278 mSettings.mPermissions.put(info.name, bp);
1279 }
1280 mSettings.writeLP();
1281 return added;
1282 }
1283 }
1284
1285 public void removePermission(String name) {
1286 synchronized (mPackages) {
1287 checkPermissionTreeLP(name);
1288 BasePermission bp = mSettings.mPermissions.get(name);
1289 if (bp != null) {
1290 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1291 throw new SecurityException(
1292 "Not allowed to modify non-dynamic permission "
1293 + name);
1294 }
1295 mSettings.mPermissions.remove(name);
1296 mSettings.writeLP();
1297 }
1298 }
1299 }
1300
Dianne Hackborn854060af2009-07-09 18:14:31 -07001301 public boolean isProtectedBroadcast(String actionName) {
1302 synchronized (mPackages) {
1303 return mProtectedBroadcasts.contains(actionName);
1304 }
1305 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307 public int checkSignatures(String pkg1, String pkg2) {
1308 synchronized (mPackages) {
1309 PackageParser.Package p1 = mPackages.get(pkg1);
1310 PackageParser.Package p2 = mPackages.get(pkg2);
1311 if (p1 == null || p1.mExtras == null
1312 || p2 == null || p2.mExtras == null) {
1313 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1314 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001315 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 }
1317 }
1318
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001319 public int checkUidSignatures(int uid1, int uid2) {
1320 synchronized (mPackages) {
1321 Signature[] s1;
1322 Signature[] s2;
1323 Object obj = mSettings.getUserIdLP(uid1);
1324 if (obj != null) {
1325 if (obj instanceof SharedUserSetting) {
1326 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1327 } else if (obj instanceof PackageSetting) {
1328 s1 = ((PackageSetting)obj).signatures.mSignatures;
1329 } else {
1330 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1331 }
1332 } else {
1333 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1334 }
1335 obj = mSettings.getUserIdLP(uid2);
1336 if (obj != null) {
1337 if (obj instanceof SharedUserSetting) {
1338 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1339 } else if (obj instanceof PackageSetting) {
1340 s2 = ((PackageSetting)obj).signatures.mSignatures;
1341 } else {
1342 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1343 }
1344 } else {
1345 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1346 }
1347 return checkSignaturesLP(s1, s2);
1348 }
1349 }
1350
1351 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1352 if (s1 == null) {
1353 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1355 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1356 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001357 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1359 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001360 final int N1 = s1.length;
1361 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 for (int i=0; i<N1; i++) {
1363 boolean match = false;
1364 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001365 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 match = true;
1367 break;
1368 }
1369 }
1370 if (!match) {
1371 return PackageManager.SIGNATURE_NO_MATCH;
1372 }
1373 }
1374 return PackageManager.SIGNATURE_MATCH;
1375 }
1376
1377 public String[] getPackagesForUid(int uid) {
1378 synchronized (mPackages) {
1379 Object obj = mSettings.getUserIdLP(uid);
1380 if (obj instanceof SharedUserSetting) {
1381 SharedUserSetting sus = (SharedUserSetting)obj;
1382 final int N = sus.packages.size();
1383 String[] res = new String[N];
1384 Iterator<PackageSetting> it = sus.packages.iterator();
1385 int i=0;
1386 while (it.hasNext()) {
1387 res[i++] = it.next().name;
1388 }
1389 return res;
1390 } else if (obj instanceof PackageSetting) {
1391 PackageSetting ps = (PackageSetting)obj;
1392 return new String[] { ps.name };
1393 }
1394 }
1395 return null;
1396 }
1397
1398 public String getNameForUid(int uid) {
1399 synchronized (mPackages) {
1400 Object obj = mSettings.getUserIdLP(uid);
1401 if (obj instanceof SharedUserSetting) {
1402 SharedUserSetting sus = (SharedUserSetting)obj;
1403 return sus.name + ":" + sus.userId;
1404 } else if (obj instanceof PackageSetting) {
1405 PackageSetting ps = (PackageSetting)obj;
1406 return ps.name;
1407 }
1408 }
1409 return null;
1410 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 public int getUidForSharedUser(String sharedUserName) {
1413 if(sharedUserName == null) {
1414 return -1;
1415 }
1416 synchronized (mPackages) {
1417 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1418 if(suid == null) {
1419 return -1;
1420 }
1421 return suid.userId;
1422 }
1423 }
1424
1425 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1426 int flags) {
1427 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001428 return chooseBestActivity(intent, resolvedType, flags, query);
1429 }
1430
Mihai Predaeae850c2009-05-13 10:13:48 +02001431 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1432 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 if (query != null) {
1434 final int N = query.size();
1435 if (N == 1) {
1436 return query.get(0);
1437 } else if (N > 1) {
1438 // If there is more than one activity with the same priority,
1439 // then let the user decide between them.
1440 ResolveInfo r0 = query.get(0);
1441 ResolveInfo r1 = query.get(1);
1442 if (false) {
1443 System.out.println(r0.activityInfo.name +
1444 "=" + r0.priority + " vs " +
1445 r1.activityInfo.name +
1446 "=" + r1.priority);
1447 }
1448 // If the first activity has a higher priority, or a different
1449 // default, then it is always desireable to pick it.
1450 if (r0.priority != r1.priority
1451 || r0.preferredOrder != r1.preferredOrder
1452 || r0.isDefault != r1.isDefault) {
1453 return query.get(0);
1454 }
1455 // If we have saved a preference for a preferred activity for
1456 // this Intent, use that.
1457 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1458 flags, query, r0.priority);
1459 if (ri != null) {
1460 return ri;
1461 }
1462 return mResolveInfo;
1463 }
1464 }
1465 return null;
1466 }
1467
1468 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1469 int flags, List<ResolveInfo> query, int priority) {
1470 synchronized (mPackages) {
1471 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1472 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001473 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1475 if (prefs != null && prefs.size() > 0) {
1476 // First figure out how good the original match set is.
1477 // We will only allow preferred activities that came
1478 // from the same match quality.
1479 int match = 0;
1480 final int N = query.size();
1481 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1482 for (int j=0; j<N; j++) {
1483 ResolveInfo ri = query.get(j);
1484 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1485 + ": 0x" + Integer.toHexString(match));
1486 if (ri.match > match) match = ri.match;
1487 }
1488 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1489 + Integer.toHexString(match));
1490 match &= IntentFilter.MATCH_CATEGORY_MASK;
1491 final int M = prefs.size();
1492 for (int i=0; i<M; i++) {
1493 PreferredActivity pa = prefs.get(i);
1494 if (pa.mMatch != match) {
1495 continue;
1496 }
1497 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1498 if (DEBUG_PREFERRED) {
1499 Log.v(TAG, "Got preferred activity:");
1500 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1501 }
1502 if (ai != null) {
1503 for (int j=0; j<N; j++) {
1504 ResolveInfo ri = query.get(j);
1505 if (!ri.activityInfo.applicationInfo.packageName
1506 .equals(ai.applicationInfo.packageName)) {
1507 continue;
1508 }
1509 if (!ri.activityInfo.name.equals(ai.name)) {
1510 continue;
1511 }
1512
1513 // Okay we found a previously set preferred app.
1514 // If the result set is different from when this
1515 // was created, we need to clear it and re-ask the
1516 // user their preference.
1517 if (!pa.sameSet(query, priority)) {
1518 Log.i(TAG, "Result set changed, dropping preferred activity for "
1519 + intent + " type " + resolvedType);
1520 mSettings.mPreferredActivities.removeFilter(pa);
1521 return null;
1522 }
1523
1524 // Yay!
1525 return ri;
1526 }
1527 }
1528 }
1529 }
1530 }
1531 return null;
1532 }
1533
1534 public List<ResolveInfo> queryIntentActivities(Intent intent,
1535 String resolvedType, int flags) {
1536 ComponentName comp = intent.getComponent();
1537 if (comp != null) {
1538 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1539 ActivityInfo ai = getActivityInfo(comp, flags);
1540 if (ai != null) {
1541 ResolveInfo ri = new ResolveInfo();
1542 ri.activityInfo = ai;
1543 list.add(ri);
1544 }
1545 return list;
1546 }
1547
1548 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001549 String pkgName = intent.getPackage();
1550 if (pkgName == null) {
1551 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1552 resolvedType, flags);
1553 }
1554 PackageParser.Package pkg = mPackages.get(pkgName);
1555 if (pkg != null) {
1556 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1557 resolvedType, flags, pkg.activities);
1558 }
1559 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 }
1561 }
1562
1563 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1564 Intent[] specifics, String[] specificTypes, Intent intent,
1565 String resolvedType, int flags) {
1566 final String resultsAction = intent.getAction();
1567
1568 List<ResolveInfo> results = queryIntentActivities(
1569 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1570 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1571
1572 int specificsPos = 0;
1573 int N;
1574
1575 // todo: note that the algorithm used here is O(N^2). This
1576 // isn't a problem in our current environment, but if we start running
1577 // into situations where we have more than 5 or 10 matches then this
1578 // should probably be changed to something smarter...
1579
1580 // First we go through and resolve each of the specific items
1581 // that were supplied, taking care of removing any corresponding
1582 // duplicate items in the generic resolve list.
1583 if (specifics != null) {
1584 for (int i=0; i<specifics.length; i++) {
1585 final Intent sintent = specifics[i];
1586 if (sintent == null) {
1587 continue;
1588 }
1589
1590 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1591 String action = sintent.getAction();
1592 if (resultsAction != null && resultsAction.equals(action)) {
1593 // If this action was explicitly requested, then don't
1594 // remove things that have it.
1595 action = null;
1596 }
1597 ComponentName comp = sintent.getComponent();
1598 ResolveInfo ri = null;
1599 ActivityInfo ai = null;
1600 if (comp == null) {
1601 ri = resolveIntent(
1602 sintent,
1603 specificTypes != null ? specificTypes[i] : null,
1604 flags);
1605 if (ri == null) {
1606 continue;
1607 }
1608 if (ri == mResolveInfo) {
1609 // ACK! Must do something better with this.
1610 }
1611 ai = ri.activityInfo;
1612 comp = new ComponentName(ai.applicationInfo.packageName,
1613 ai.name);
1614 } else {
1615 ai = getActivityInfo(comp, flags);
1616 if (ai == null) {
1617 continue;
1618 }
1619 }
1620
1621 // Look for any generic query activities that are duplicates
1622 // of this specific one, and remove them from the results.
1623 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1624 N = results.size();
1625 int j;
1626 for (j=specificsPos; j<N; j++) {
1627 ResolveInfo sri = results.get(j);
1628 if ((sri.activityInfo.name.equals(comp.getClassName())
1629 && sri.activityInfo.applicationInfo.packageName.equals(
1630 comp.getPackageName()))
1631 || (action != null && sri.filter.matchAction(action))) {
1632 results.remove(j);
1633 if (Config.LOGV) Log.v(
1634 TAG, "Removing duplicate item from " + j
1635 + " due to specific " + specificsPos);
1636 if (ri == null) {
1637 ri = sri;
1638 }
1639 j--;
1640 N--;
1641 }
1642 }
1643
1644 // Add this specific item to its proper place.
1645 if (ri == null) {
1646 ri = new ResolveInfo();
1647 ri.activityInfo = ai;
1648 }
1649 results.add(specificsPos, ri);
1650 ri.specificIndex = i;
1651 specificsPos++;
1652 }
1653 }
1654
1655 // Now we go through the remaining generic results and remove any
1656 // duplicate actions that are found here.
1657 N = results.size();
1658 for (int i=specificsPos; i<N-1; i++) {
1659 final ResolveInfo rii = results.get(i);
1660 if (rii.filter == null) {
1661 continue;
1662 }
1663
1664 // Iterate over all of the actions of this result's intent
1665 // filter... typically this should be just one.
1666 final Iterator<String> it = rii.filter.actionsIterator();
1667 if (it == null) {
1668 continue;
1669 }
1670 while (it.hasNext()) {
1671 final String action = it.next();
1672 if (resultsAction != null && resultsAction.equals(action)) {
1673 // If this action was explicitly requested, then don't
1674 // remove things that have it.
1675 continue;
1676 }
1677 for (int j=i+1; j<N; j++) {
1678 final ResolveInfo rij = results.get(j);
1679 if (rij.filter != null && rij.filter.hasAction(action)) {
1680 results.remove(j);
1681 if (Config.LOGV) Log.v(
1682 TAG, "Removing duplicate item from " + j
1683 + " due to action " + action + " at " + i);
1684 j--;
1685 N--;
1686 }
1687 }
1688 }
1689
1690 // If the caller didn't request filter information, drop it now
1691 // so we don't have to marshall/unmarshall it.
1692 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1693 rii.filter = null;
1694 }
1695 }
1696
1697 // Filter out the caller activity if so requested.
1698 if (caller != null) {
1699 N = results.size();
1700 for (int i=0; i<N; i++) {
1701 ActivityInfo ainfo = results.get(i).activityInfo;
1702 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1703 && caller.getClassName().equals(ainfo.name)) {
1704 results.remove(i);
1705 break;
1706 }
1707 }
1708 }
1709
1710 // If the caller didn't request filter information,
1711 // drop them now so we don't have to
1712 // marshall/unmarshall it.
1713 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1714 N = results.size();
1715 for (int i=0; i<N; i++) {
1716 results.get(i).filter = null;
1717 }
1718 }
1719
1720 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1721 return results;
1722 }
1723
1724 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1725 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001726 ComponentName comp = intent.getComponent();
1727 if (comp != null) {
1728 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1729 ActivityInfo ai = getReceiverInfo(comp, flags);
1730 if (ai != null) {
1731 ResolveInfo ri = new ResolveInfo();
1732 ri.activityInfo = ai;
1733 list.add(ri);
1734 }
1735 return list;
1736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001739 String pkgName = intent.getPackage();
1740 if (pkgName == null) {
1741 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1742 resolvedType, flags);
1743 }
1744 PackageParser.Package pkg = mPackages.get(pkgName);
1745 if (pkg != null) {
1746 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1747 resolvedType, flags, pkg.receivers);
1748 }
1749 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 }
1751 }
1752
1753 public ResolveInfo resolveService(Intent intent, String resolvedType,
1754 int flags) {
1755 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1756 flags);
1757 if (query != null) {
1758 if (query.size() >= 1) {
1759 // If there is more than one service with the same priority,
1760 // just arbitrarily pick the first one.
1761 return query.get(0);
1762 }
1763 }
1764 return null;
1765 }
1766
1767 public List<ResolveInfo> queryIntentServices(Intent intent,
1768 String resolvedType, int flags) {
1769 ComponentName comp = intent.getComponent();
1770 if (comp != null) {
1771 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1772 ServiceInfo si = getServiceInfo(comp, flags);
1773 if (si != null) {
1774 ResolveInfo ri = new ResolveInfo();
1775 ri.serviceInfo = si;
1776 list.add(ri);
1777 }
1778 return list;
1779 }
1780
1781 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001782 String pkgName = intent.getPackage();
1783 if (pkgName == null) {
1784 return (List<ResolveInfo>)mServices.queryIntent(intent,
1785 resolvedType, flags);
1786 }
1787 PackageParser.Package pkg = mPackages.get(pkgName);
1788 if (pkg != null) {
1789 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1790 resolvedType, flags, pkg.services);
1791 }
1792 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 }
1794 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 public List<PackageInfo> getInstalledPackages(int flags) {
1797 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1798
1799 synchronized (mPackages) {
1800 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1801 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1802 while (i.hasNext()) {
1803 final PackageSetting ps = i.next();
1804 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1805 if(psPkg != null) {
1806 finalList.add(psPkg);
1807 }
1808 }
1809 }
1810 else {
1811 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1812 while (i.hasNext()) {
1813 final PackageParser.Package p = i.next();
1814 if (p.applicationInfo != null) {
1815 PackageInfo pi = generatePackageInfo(p, flags);
1816 if(pi != null) {
1817 finalList.add(pi);
1818 }
1819 }
1820 }
1821 }
1822 }
1823 return finalList;
1824 }
1825
1826 public List<ApplicationInfo> getInstalledApplications(int flags) {
1827 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1828 synchronized(mPackages) {
1829 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1830 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1831 while (i.hasNext()) {
1832 final PackageSetting ps = i.next();
1833 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1834 if(ai != null) {
1835 finalList.add(ai);
1836 }
1837 }
1838 }
1839 else {
1840 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1841 while (i.hasNext()) {
1842 final PackageParser.Package p = i.next();
1843 if (p.applicationInfo != null) {
1844 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1845 if(ai != null) {
1846 finalList.add(ai);
1847 }
1848 }
1849 }
1850 }
1851 }
1852 return finalList;
1853 }
1854
1855 public List<ApplicationInfo> getPersistentApplications(int flags) {
1856 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1857
1858 synchronized (mPackages) {
1859 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1860 while (i.hasNext()) {
1861 PackageParser.Package p = i.next();
1862 if (p.applicationInfo != null
1863 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1864 && (!mSafeMode || (p.applicationInfo.flags
1865 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1866 finalList.add(p.applicationInfo);
1867 }
1868 }
1869 }
1870
1871 return finalList;
1872 }
1873
1874 public ProviderInfo resolveContentProvider(String name, int flags) {
1875 synchronized (mPackages) {
1876 final PackageParser.Provider provider = mProviders.get(name);
1877 return provider != null
1878 && mSettings.isEnabledLP(provider.info, flags)
1879 && (!mSafeMode || (provider.info.applicationInfo.flags
1880 &ApplicationInfo.FLAG_SYSTEM) != 0)
1881 ? PackageParser.generateProviderInfo(provider, flags)
1882 : null;
1883 }
1884 }
1885
Fred Quintana718d8a22009-04-29 17:53:20 -07001886 /**
1887 * @deprecated
1888 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 public void querySyncProviders(List outNames, List outInfo) {
1890 synchronized (mPackages) {
1891 Iterator<Map.Entry<String, PackageParser.Provider>> i
1892 = mProviders.entrySet().iterator();
1893
1894 while (i.hasNext()) {
1895 Map.Entry<String, PackageParser.Provider> entry = i.next();
1896 PackageParser.Provider p = entry.getValue();
1897
1898 if (p.syncable
1899 && (!mSafeMode || (p.info.applicationInfo.flags
1900 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1901 outNames.add(entry.getKey());
1902 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1903 }
1904 }
1905 }
1906 }
1907
1908 public List<ProviderInfo> queryContentProviders(String processName,
1909 int uid, int flags) {
1910 ArrayList<ProviderInfo> finalList = null;
1911
1912 synchronized (mPackages) {
1913 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1914 while (i.hasNext()) {
1915 PackageParser.Provider p = i.next();
1916 if (p.info.authority != null
1917 && (processName == null ||
1918 (p.info.processName.equals(processName)
1919 && p.info.applicationInfo.uid == uid))
1920 && mSettings.isEnabledLP(p.info, flags)
1921 && (!mSafeMode || (p.info.applicationInfo.flags
1922 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1923 if (finalList == null) {
1924 finalList = new ArrayList<ProviderInfo>(3);
1925 }
1926 finalList.add(PackageParser.generateProviderInfo(p,
1927 flags));
1928 }
1929 }
1930 }
1931
1932 if (finalList != null) {
1933 Collections.sort(finalList, mProviderInitOrderSorter);
1934 }
1935
1936 return finalList;
1937 }
1938
1939 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1940 int flags) {
1941 synchronized (mPackages) {
1942 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1943 return PackageParser.generateInstrumentationInfo(i, flags);
1944 }
1945 }
1946
1947 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1948 int flags) {
1949 ArrayList<InstrumentationInfo> finalList =
1950 new ArrayList<InstrumentationInfo>();
1951
1952 synchronized (mPackages) {
1953 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1954 while (i.hasNext()) {
1955 PackageParser.Instrumentation p = i.next();
1956 if (targetPackage == null
1957 || targetPackage.equals(p.info.targetPackage)) {
1958 finalList.add(PackageParser.generateInstrumentationInfo(p,
1959 flags));
1960 }
1961 }
1962 }
1963
1964 return finalList;
1965 }
1966
1967 private void scanDirLI(File dir, int flags, int scanMode) {
1968 Log.d(TAG, "Scanning app dir " + dir);
1969
1970 String[] files = dir.list();
1971
1972 int i;
1973 for (i=0; i<files.length; i++) {
1974 File file = new File(dir, files[i]);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001975 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1977 }
1978 }
1979
1980 private static void reportSettingsProblem(int priority, String msg) {
1981 try {
1982 File dataDir = Environment.getDataDirectory();
1983 File systemDir = new File(dataDir, "system");
1984 File fname = new File(systemDir, "uiderrors.txt");
1985 FileOutputStream out = new FileOutputStream(fname, true);
1986 PrintWriter pw = new PrintWriter(out);
1987 pw.println(msg);
1988 pw.close();
1989 FileUtils.setPermissions(
1990 fname.toString(),
1991 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1992 -1, -1);
1993 } catch (java.io.IOException e) {
1994 }
1995 Log.println(priority, TAG, msg);
1996 }
1997
1998 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1999 PackageParser.Package pkg, File srcFile, int parseFlags) {
2000 if (GET_CERTIFICATES) {
2001 if (ps == null || !ps.codePath.equals(srcFile)
2002 || ps.getTimeStamp() != srcFile.lastModified()) {
2003 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2004 if (!pp.collectCertificates(pkg, parseFlags)) {
2005 mLastScanError = pp.getParseError();
2006 return false;
2007 }
2008 }
2009 }
2010 return true;
2011 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 /*
2014 * Scan a package and return the newly parsed package.
2015 * Returns null in case of errors and the error code is stored in mLastScanError
2016 */
2017 private PackageParser.Package scanPackageLI(File scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002018 int parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 int scanMode) {
2020 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2021 parseFlags |= mDefParseFlags;
2022 PackageParser pp = new PackageParser(scanFile.getPath());
2023 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002025 scanFile.getPath(),
2026 mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 if (pkg == null) {
2028 mLastScanError = pp.getParseError();
2029 return null;
2030 }
2031 PackageSetting ps;
2032 PackageSetting updatedPkg;
2033 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002034 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2036 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002037 // Verify certificates first
2038 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2039 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2040 return null;
2041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 if (updatedPkg != null) {
2043 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2044 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2045 }
2046 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2047 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002048 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2049 if (pkg.mVersionCode < ps.versionCode) {
2050 // The system package has been updated and the code path does not match
2051 // Ignore entry. Just return
2052 Log.w(TAG, "Package:" + pkg.packageName +
2053 " has been updated. Ignoring the one from path:"+scanFile);
2054 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2055 return null;
2056 } else {
2057 // Delete the older apk pointed to by ps
2058 // At this point, its safely assumed that package installation for
2059 // apps in system partition will go through. If not there won't be a working
2060 // version of the app
2061 synchronized (mPackages) {
2062 // Just remove the loaded entries from package lists.
2063 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002064 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002065 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2066 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 }
2069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 // The apk is forward locked (not public) if its code and resources
2071 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002072 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002074 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002077 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 }
2079
2080 private static String fixProcessName(String defProcessName,
2081 String processName, int uid) {
2082 if (processName == null) {
2083 return defProcessName;
2084 }
2085 return processName;
2086 }
2087
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002088 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2090 if (pkg.mSignatures != null) {
2091 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2092 updateSignature)) {
2093 Log.e(TAG, "Package " + pkg.packageName
2094 + " signatures do not match the previously installed version; ignoring!");
2095 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2096 return false;
2097 }
2098
2099 if (pkgSetting.sharedUser != null) {
2100 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2101 pkg.mSignatures, updateSignature)) {
2102 Log.e(TAG, "Package " + pkg.packageName
2103 + " has no signatures that match those in shared user "
2104 + pkgSetting.sharedUser.name + "; ignoring!");
2105 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2106 return false;
2107 }
2108 }
2109 } else {
2110 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2111 }
2112 return true;
2113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002114
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002115 public boolean performDexOpt(String packageName) {
2116 if (!mNoDexOpt) {
2117 return false;
2118 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002119
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002120 PackageParser.Package p;
2121 synchronized (mPackages) {
2122 p = mPackages.get(packageName);
2123 if (p == null || p.mDidDexOpt) {
2124 return false;
2125 }
2126 }
2127 synchronized (mInstallLock) {
2128 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2129 }
2130 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002131
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002132 static final int DEX_OPT_SKIPPED = 0;
2133 static final int DEX_OPT_PERFORMED = 1;
2134 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002135
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002136 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2137 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002138 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002139 String path = pkg.mScanPath;
2140 int ret = 0;
2141 try {
2142 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002143 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002144 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002145 pkg.mDidDexOpt = true;
2146 performed = true;
2147 }
2148 } catch (FileNotFoundException e) {
2149 Log.w(TAG, "Apk not found for dexopt: " + path);
2150 ret = -1;
2151 } catch (IOException e) {
2152 Log.w(TAG, "Exception reading apk: " + path, e);
2153 ret = -1;
2154 }
2155 if (ret < 0) {
2156 //error from installer
2157 return DEX_OPT_FAILED;
2158 }
2159 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002160
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002161 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2162 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002163
2164 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2165 return Environment.isEncryptedFilesystemEnabled() &&
2166 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2167 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 private PackageParser.Package scanPackageLI(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 PackageParser.Package pkg, int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002171 File scanFile = new File(pkg.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 mScanningPath = scanFile;
2173 if (pkg == null) {
2174 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2175 return null;
2176 }
2177
2178 final String pkgName = pkg.applicationInfo.packageName;
2179 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2180 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2181 }
2182
2183 if (pkgName.equals("android")) {
2184 synchronized (mPackages) {
2185 if (mAndroidApplication != null) {
2186 Log.w(TAG, "*************************************************");
2187 Log.w(TAG, "Core android package being redefined. Skipping.");
2188 Log.w(TAG, " file=" + mScanningPath);
2189 Log.w(TAG, "*************************************************");
2190 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2191 return null;
2192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194 // Set up information for our fall-back user intent resolution
2195 // activity.
2196 mPlatformPackage = pkg;
2197 pkg.mVersionCode = mSdkVersion;
2198 mAndroidApplication = pkg.applicationInfo;
2199 mResolveActivity.applicationInfo = mAndroidApplication;
2200 mResolveActivity.name = ResolverActivity.class.getName();
2201 mResolveActivity.packageName = mAndroidApplication.packageName;
2202 mResolveActivity.processName = mAndroidApplication.processName;
2203 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2204 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2205 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2206 mResolveActivity.exported = true;
2207 mResolveActivity.enabled = true;
2208 mResolveInfo.activityInfo = mResolveActivity;
2209 mResolveInfo.priority = 0;
2210 mResolveInfo.preferredOrder = 0;
2211 mResolveInfo.match = 0;
2212 mResolveComponentName = new ComponentName(
2213 mAndroidApplication.packageName, mResolveActivity.name);
2214 }
2215 }
2216
2217 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2218 TAG, "Scanning package " + pkgName);
2219 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2220 Log.w(TAG, "*************************************************");
2221 Log.w(TAG, "Application package " + pkgName
2222 + " already installed. Skipping duplicate.");
2223 Log.w(TAG, "*************************************************");
2224 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2225 return null;
2226 }
2227
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002228 // Initialize package source and resource directories
2229 File destResourceFile = null;
2230 File destCodeFile = null;
2231 if ((scanMode & SCAN_NO_PATHS) == 0) {
2232 boolean fwdLocked = (parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0;
2233 final String pkgFileName = pkgName + ".apk";
2234 File destDir = null;
2235
2236 if (fwdLocked) {
2237 destDir = mDrmAppPrivateInstallDir;
2238 destResourceFile = new File(mAppInstallDir, pkgName + ".zip");
2239 } else {
2240 boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
2241 if (!onSd) {
2242 destDir = mAppInstallDir;
2243 } else {
2244 String cachePath = getSdDir(pkgName);
2245 if (cachePath == null) {
2246 Log.e(TAG, "Secure container path for pkg: " + pkgName + " at location: " + cachePath +
2247 " not found");
2248 mLastScanError = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
2249 return null;
2250 }
2251 destDir = new File(cachePath);
2252 }
2253 destResourceFile = new File(destDir, pkgFileName);
2254 }
2255 destCodeFile = new File(destDir, pkgFileName);
2256 pkg.mPath = destCodeFile.getAbsolutePath();
2257 } else {
2258 pkg.mPath = pkg.mScanPath;
2259 destCodeFile = new File(pkg.mScanPath);
2260 destResourceFile = new File(pkg.mScanPath);
2261 }
2262 pkg.applicationInfo.sourceDir = destCodeFile.getAbsolutePath();
2263 pkg.applicationInfo.publicSourceDir = destResourceFile.getAbsolutePath();
2264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265 SharedUserSetting suid = null;
2266 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270 synchronized (mPackages) {
2271 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002272 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2273 if (mTmpSharedLibraries == null ||
2274 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2275 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2276 }
2277 int num = 0;
2278 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2279 for (int i=0; i<N; i++) {
2280 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002281 if (file == null) {
2282 Log.e(TAG, "Package " + pkg.packageName
2283 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002284 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2286 return null;
2287 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002288 mTmpSharedLibraries[num] = file;
2289 num++;
2290 }
2291 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2292 for (int i=0; i<N; i++) {
2293 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2294 if (file == null) {
2295 Log.w(TAG, "Package " + pkg.packageName
2296 + " desires unavailable shared library "
2297 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2298 } else {
2299 mTmpSharedLibraries[num] = file;
2300 num++;
2301 }
2302 }
2303 if (num > 0) {
2304 pkg.usesLibraryFiles = new String[num];
2305 System.arraycopy(mTmpSharedLibraries, 0,
2306 pkg.usesLibraryFiles, 0, num);
2307 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002308
Dianne Hackborn49237342009-08-27 20:08:01 -07002309 if (pkg.reqFeatures != null) {
2310 N = pkg.reqFeatures.size();
2311 for (int i=0; i<N; i++) {
2312 FeatureInfo fi = pkg.reqFeatures.get(i);
2313 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2314 // Don't care.
2315 continue;
2316 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002317
Dianne Hackborn49237342009-08-27 20:08:01 -07002318 if (fi.name != null) {
2319 if (mAvailableFeatures.get(fi.name) == null) {
2320 Log.e(TAG, "Package " + pkg.packageName
2321 + " requires unavailable feature "
2322 + fi.name + "; failing!");
2323 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2324 return null;
2325 }
2326 }
2327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002328 }
2329 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 if (pkg.mSharedUserId != null) {
2332 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2333 pkg.applicationInfo.flags, true);
2334 if (suid == null) {
2335 Log.w(TAG, "Creating application package " + pkgName
2336 + " for shared user failed");
2337 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2338 return null;
2339 }
2340 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2341 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2342 + suid.userId + "): packages=" + suid.packages);
2343 }
2344 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002345
2346 // Just create the setting, don't add it yet. For already existing packages
2347 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2349 destResourceFile, pkg.applicationInfo.flags, true, false);
2350 if (pkgSetting == null) {
2351 Log.w(TAG, "Creating application package " + pkgName + " failed");
2352 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2353 return null;
2354 }
2355 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2356 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002359 pkg.applicationInfo.uid = pkgSetting.userId;
2360 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002361
2362 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2364 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2365 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2366 return null;
2367 }
2368 // The signature has changed, but this package is in the system
2369 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002370 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 // However... if this package is part of a shared user, but it
2372 // doesn't match the signature of the shared user, let's fail.
2373 // What this means is that you can't change the signatures
2374 // associated with an overall shared user, which doesn't seem all
2375 // that unreasonable.
2376 if (pkgSetting.sharedUser != null) {
2377 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2378 pkg.mSignatures, false)) {
2379 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2380 return null;
2381 }
2382 }
2383 removeExisting = true;
2384 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002385
The Android Open Source Project10592532009-03-18 17:39:46 -07002386 // Verify that this new package doesn't have any content providers
2387 // that conflict with existing packages. Only do this if the
2388 // package isn't already installed, since we don't want to break
2389 // things that are installed.
2390 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2391 int N = pkg.providers.size();
2392 int i;
2393 for (i=0; i<N; i++) {
2394 PackageParser.Provider p = pkg.providers.get(i);
2395 String names[] = p.info.authority.split(";");
2396 for (int j = 0; j < names.length; j++) {
2397 if (mProviders.containsKey(names[j])) {
2398 PackageParser.Provider other = mProviders.get(names[j]);
2399 Log.w(TAG, "Can't install because provider name " + names[j] +
2400 " (in package " + pkg.applicationInfo.packageName +
2401 ") is already used by "
2402 + ((other != null && other.component != null)
2403 ? other.component.getPackageName() : "?"));
2404 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2405 return null;
2406 }
2407 }
2408 }
2409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 }
2411
2412 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002413 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002415 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002416 if (ret != 0) {
2417 String msg = "System package " + pkg.packageName
2418 + " could not have data directory erased after signature change.";
2419 reportSettingsProblem(Log.WARN, msg);
2420 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2421 return null;
2422 }
2423 }
2424 Log.w(TAG, "System package " + pkg.packageName
2425 + " signature changed: existing data removed.");
2426 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2427 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 long scanFileTime = scanFile.lastModified();
2430 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2431 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2432 pkg.applicationInfo.processName = fixProcessName(
2433 pkg.applicationInfo.packageName,
2434 pkg.applicationInfo.processName,
2435 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436
2437 File dataPath;
2438 if (mPlatformPackage == pkg) {
2439 // The system package is special.
2440 dataPath = new File (Environment.getDataDirectory(), "system");
2441 pkg.applicationInfo.dataDir = dataPath.getPath();
2442 } else {
2443 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002444 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2445 if (useEncryptedFSDir) {
2446 dataPath = new File(mSecureAppDataDir, pkgName);
2447 } else {
2448 dataPath = new File(mAppDataDir, pkgName);
2449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 if (dataPath.exists()) {
2451 mOutPermissions[1] = 0;
2452 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2453 if (mOutPermissions[1] == pkg.applicationInfo.uid
2454 || !Process.supportsProcesses()) {
2455 pkg.applicationInfo.dataDir = dataPath.getPath();
2456 } else {
2457 boolean recovered = false;
2458 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2459 // If this is a system app, we can at least delete its
2460 // current data so the application will still work.
2461 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002462 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 if(ret >= 0) {
2464 // Old data gone!
2465 String msg = "System package " + pkg.packageName
2466 + " has changed from uid: "
2467 + mOutPermissions[1] + " to "
2468 + pkg.applicationInfo.uid + "; old data erased";
2469 reportSettingsProblem(Log.WARN, msg);
2470 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002473 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002474 pkg.applicationInfo.uid);
2475 if (ret == -1) {
2476 // Ack should not happen!
2477 msg = "System package " + pkg.packageName
2478 + " could not have data directory re-created after delete.";
2479 reportSettingsProblem(Log.WARN, msg);
2480 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2481 return null;
2482 }
2483 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 if (!recovered) {
2486 mHasSystemUidErrors = true;
2487 }
2488 }
2489 if (!recovered) {
2490 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2491 + pkg.applicationInfo.uid + "/fs_"
2492 + mOutPermissions[1];
2493 String msg = "Package " + pkg.packageName
2494 + " has mismatched uid: "
2495 + mOutPermissions[1] + " on disk, "
2496 + pkg.applicationInfo.uid + " in settings";
2497 synchronized (mPackages) {
2498 if (!mReportedUidError) {
2499 mReportedUidError = true;
2500 msg = msg + "; read messages:\n"
2501 + mSettings.getReadMessagesLP();
2502 }
2503 reportSettingsProblem(Log.ERROR, msg);
2504 }
2505 }
2506 }
2507 pkg.applicationInfo.dataDir = dataPath.getPath();
2508 } else {
2509 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2510 Log.v(TAG, "Want this data dir: " + dataPath);
2511 //invoke installer to do the actual installation
2512 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002513 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002514 pkg.applicationInfo.uid);
2515 if(ret < 0) {
2516 // Error from installer
2517 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2518 return null;
2519 }
2520 } else {
2521 dataPath.mkdirs();
2522 if (dataPath.exists()) {
2523 FileUtils.setPermissions(
2524 dataPath.toString(),
2525 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2526 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2527 }
2528 }
2529 if (dataPath.exists()) {
2530 pkg.applicationInfo.dataDir = dataPath.getPath();
2531 } else {
2532 Log.w(TAG, "Unable to create data directory: " + dataPath);
2533 pkg.applicationInfo.dataDir = null;
2534 }
2535 }
2536 }
2537
2538 // Perform shared library installation and dex validation and
2539 // optimization, if this is not a system app.
2540 if (mInstaller != null) {
2541 String path = scanFile.getPath();
2542 if (scanFileNewer) {
2543 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002544 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2545 if (err != PackageManager.INSTALL_SUCCEEDED) {
2546 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 return null;
2548 }
2549 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002550 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002551
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002552 if ((scanMode&SCAN_NO_DEX) == 0) {
2553 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2555 return null;
2556 }
2557 }
2558 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002560 if (mFactoryTest && pkg.requestedPermissions.contains(
2561 android.Manifest.permission.FACTORY_TEST)) {
2562 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2563 }
2564
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002565 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 if ((scanMode&SCAN_MONITOR) != 0) {
2567 pkg.mPath = destCodeFile.getAbsolutePath();
2568 mAppDirs.put(pkg.mPath, pkg);
2569 }
2570
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002571 // Request the ActivityManager to kill the process(only for existing packages)
2572 // so that we do not end up in a confused state while the user is still using the older
2573 // version of the application while the new one gets installed.
2574 IActivityManager am = ActivityManagerNative.getDefault();
2575 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2576 try {
2577 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2578 pkg.applicationInfo.uid);
2579 } catch (RemoteException e) {
2580 }
2581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002582 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002584 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002586 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 int N = pkg.providers.size();
2588 StringBuilder r = null;
2589 int i;
2590 for (i=0; i<N; i++) {
2591 PackageParser.Provider p = pkg.providers.get(i);
2592 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2593 p.info.processName, pkg.applicationInfo.uid);
2594 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2595 p.info.name), p);
2596 p.syncable = p.info.isSyncable;
2597 String names[] = p.info.authority.split(";");
2598 p.info.authority = null;
2599 for (int j = 0; j < names.length; j++) {
2600 if (j == 1 && p.syncable) {
2601 // We only want the first authority for a provider to possibly be
2602 // syncable, so if we already added this provider using a different
2603 // authority clear the syncable flag. We copy the provider before
2604 // changing it because the mProviders object contains a reference
2605 // to a provider that we don't want to change.
2606 // Only do this for the second authority since the resulting provider
2607 // object can be the same for all future authorities for this provider.
2608 p = new PackageParser.Provider(p);
2609 p.syncable = false;
2610 }
2611 if (!mProviders.containsKey(names[j])) {
2612 mProviders.put(names[j], p);
2613 if (p.info.authority == null) {
2614 p.info.authority = names[j];
2615 } else {
2616 p.info.authority = p.info.authority + ";" + names[j];
2617 }
2618 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2619 Log.d(TAG, "Registered content provider: " + names[j] +
2620 ", className = " + p.info.name +
2621 ", isSyncable = " + p.info.isSyncable);
2622 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002623 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 Log.w(TAG, "Skipping provider name " + names[j] +
2625 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002626 "): name already used by "
2627 + ((other != null && other.component != null)
2628 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 }
2630 }
2631 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2632 if (r == null) {
2633 r = new StringBuilder(256);
2634 } else {
2635 r.append(' ');
2636 }
2637 r.append(p.info.name);
2638 }
2639 }
2640 if (r != null) {
2641 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2642 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 N = pkg.services.size();
2645 r = null;
2646 for (i=0; i<N; i++) {
2647 PackageParser.Service s = pkg.services.get(i);
2648 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2649 s.info.processName, pkg.applicationInfo.uid);
2650 mServices.addService(s);
2651 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2652 if (r == null) {
2653 r = new StringBuilder(256);
2654 } else {
2655 r.append(' ');
2656 }
2657 r.append(s.info.name);
2658 }
2659 }
2660 if (r != null) {
2661 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2662 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002664 N = pkg.receivers.size();
2665 r = null;
2666 for (i=0; i<N; i++) {
2667 PackageParser.Activity a = pkg.receivers.get(i);
2668 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2669 a.info.processName, pkg.applicationInfo.uid);
2670 mReceivers.addActivity(a, "receiver");
2671 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2672 if (r == null) {
2673 r = new StringBuilder(256);
2674 } else {
2675 r.append(' ');
2676 }
2677 r.append(a.info.name);
2678 }
2679 }
2680 if (r != null) {
2681 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2682 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 N = pkg.activities.size();
2685 r = null;
2686 for (i=0; i<N; i++) {
2687 PackageParser.Activity a = pkg.activities.get(i);
2688 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2689 a.info.processName, pkg.applicationInfo.uid);
2690 mActivities.addActivity(a, "activity");
2691 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2692 if (r == null) {
2693 r = new StringBuilder(256);
2694 } else {
2695 r.append(' ');
2696 }
2697 r.append(a.info.name);
2698 }
2699 }
2700 if (r != null) {
2701 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2702 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 N = pkg.permissionGroups.size();
2705 r = null;
2706 for (i=0; i<N; i++) {
2707 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2708 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2709 if (cur == null) {
2710 mPermissionGroups.put(pg.info.name, pg);
2711 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2712 if (r == null) {
2713 r = new StringBuilder(256);
2714 } else {
2715 r.append(' ');
2716 }
2717 r.append(pg.info.name);
2718 }
2719 } else {
2720 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2721 + pg.info.packageName + " ignored: original from "
2722 + cur.info.packageName);
2723 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2724 if (r == null) {
2725 r = new StringBuilder(256);
2726 } else {
2727 r.append(' ');
2728 }
2729 r.append("DUP:");
2730 r.append(pg.info.name);
2731 }
2732 }
2733 }
2734 if (r != null) {
2735 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 N = pkg.permissions.size();
2739 r = null;
2740 for (i=0; i<N; i++) {
2741 PackageParser.Permission p = pkg.permissions.get(i);
2742 HashMap<String, BasePermission> permissionMap =
2743 p.tree ? mSettings.mPermissionTrees
2744 : mSettings.mPermissions;
2745 p.group = mPermissionGroups.get(p.info.group);
2746 if (p.info.group == null || p.group != null) {
2747 BasePermission bp = permissionMap.get(p.info.name);
2748 if (bp == null) {
2749 bp = new BasePermission(p.info.name, p.info.packageName,
2750 BasePermission.TYPE_NORMAL);
2751 permissionMap.put(p.info.name, bp);
2752 }
2753 if (bp.perm == null) {
2754 if (bp.sourcePackage == null
2755 || bp.sourcePackage.equals(p.info.packageName)) {
2756 BasePermission tree = findPermissionTreeLP(p.info.name);
2757 if (tree == null
2758 || tree.sourcePackage.equals(p.info.packageName)) {
2759 bp.perm = p;
2760 bp.uid = pkg.applicationInfo.uid;
2761 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2762 if (r == null) {
2763 r = new StringBuilder(256);
2764 } else {
2765 r.append(' ');
2766 }
2767 r.append(p.info.name);
2768 }
2769 } else {
2770 Log.w(TAG, "Permission " + p.info.name + " from package "
2771 + p.info.packageName + " ignored: base tree "
2772 + tree.name + " is from package "
2773 + tree.sourcePackage);
2774 }
2775 } else {
2776 Log.w(TAG, "Permission " + p.info.name + " from package "
2777 + p.info.packageName + " ignored: original from "
2778 + bp.sourcePackage);
2779 }
2780 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2781 if (r == null) {
2782 r = new StringBuilder(256);
2783 } else {
2784 r.append(' ');
2785 }
2786 r.append("DUP:");
2787 r.append(p.info.name);
2788 }
2789 } else {
2790 Log.w(TAG, "Permission " + p.info.name + " from package "
2791 + p.info.packageName + " ignored: no group "
2792 + p.group);
2793 }
2794 }
2795 if (r != null) {
2796 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2797 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 N = pkg.instrumentation.size();
2800 r = null;
2801 for (i=0; i<N; i++) {
2802 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2803 a.info.packageName = pkg.applicationInfo.packageName;
2804 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2805 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2806 a.info.dataDir = pkg.applicationInfo.dataDir;
2807 mInstrumentation.put(a.component, a);
2808 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2809 if (r == null) {
2810 r = new StringBuilder(256);
2811 } else {
2812 r.append(' ');
2813 }
2814 r.append(a.info.name);
2815 }
2816 }
2817 if (r != null) {
2818 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2819 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002820
Dianne Hackborn854060af2009-07-09 18:14:31 -07002821 if (pkg.protectedBroadcasts != null) {
2822 N = pkg.protectedBroadcasts.size();
2823 for (i=0; i<N; i++) {
2824 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2825 }
2826 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 pkgSetting.setTimeStamp(scanFileTime);
2829 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002831 return pkg;
2832 }
2833
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002834 // The following constants are returned by cachePackageSharedLibsForAbiLI
2835 // to indicate if native shared libraries were found in the package.
2836 // Values are:
2837 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2838 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2839 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2840 // in package (and not installed)
2841 //
2842 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2843 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2844 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002846 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2847 // and automatically copy them to /data/data/<appname>/lib if present.
2848 //
2849 // NOTE: this method may throw an IOException if the library cannot
2850 // be copied to its final destination, e.g. if there isn't enough
2851 // room left on the data partition, or a ZipException if the package
2852 // file is malformed.
2853 //
2854 private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg,
2855 File dataPath, File scanFile, String cpuAbi)
2856 throws IOException, ZipException {
2857 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2858 final String apkLib = "lib/";
2859 final int apkLibLen = apkLib.length();
2860 final int cpuAbiLen = cpuAbi.length();
2861 final String libPrefix = "lib";
2862 final int libPrefixLen = libPrefix.length();
2863 final String libSuffix = ".so";
2864 final int libSuffixLen = libSuffix.length();
2865 boolean hasNativeLibraries = false;
2866 boolean installedNativeLibraries = false;
2867
2868 // the minimum length of a valid native shared library of the form
2869 // lib/<something>/lib<name>.so.
2870 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2871
2872 ZipFile zipFile = new ZipFile(scanFile);
2873 Enumeration<ZipEntry> entries =
2874 (Enumeration<ZipEntry>) zipFile.entries();
2875
2876 while (entries.hasMoreElements()) {
2877 ZipEntry entry = entries.nextElement();
2878 // skip directories
2879 if (entry.isDirectory()) {
2880 continue;
2881 }
2882 String entryName = entry.getName();
2883
2884 // check that the entry looks like lib/<something>/lib<name>.so
2885 // here, but don't check the ABI just yet.
2886 //
2887 // - must be sufficiently long
2888 // - must end with libSuffix, i.e. ".so"
2889 // - must start with apkLib, i.e. "lib/"
2890 if (entryName.length() < minEntryLen ||
2891 !entryName.endsWith(libSuffix) ||
2892 !entryName.startsWith(apkLib) ) {
2893 continue;
2894 }
2895
2896 // file name must start with libPrefix, i.e. "lib"
2897 int lastSlash = entryName.lastIndexOf('/');
2898
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002899 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002900 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2901 continue;
2902 }
2903
2904 hasNativeLibraries = true;
2905
2906 // check the cpuAbi now, between lib/ and /lib<name>.so
2907 //
2908 if (lastSlash != apkLibLen + cpuAbiLen ||
2909 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2910 continue;
2911
2912 // extract the library file name, ensure it doesn't contain
2913 // weird characters. we're guaranteed here that it doesn't contain
2914 // a directory separator though.
2915 String libFileName = entryName.substring(lastSlash+1);
2916 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2917 continue;
2918 }
2919
2920 installedNativeLibraries = true;
2921
2922 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2923 File.separator + libFileName;
2924 File sharedLibraryFile = new File(sharedLibraryFilePath);
2925 if (! sharedLibraryFile.exists() ||
2926 sharedLibraryFile.length() != entry.getSize() ||
2927 sharedLibraryFile.lastModified() != entry.getTime()) {
2928 if (Config.LOGD) {
2929 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002931 if (mInstaller == null) {
2932 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002933 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002934 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2935 sharedLibraryFile);
2936 }
2937 }
2938 if (!hasNativeLibraries)
2939 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2940
2941 if (!installedNativeLibraries)
2942 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
2943
2944 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2945 }
2946
2947 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
2948 // and copy them to /data/data/<appname>/lib.
2949 //
2950 // This function will first try the main CPU ABI defined by Build.CPU_ABI
2951 // (which corresponds to ro.product.cpu.abi), and also try an alternate
2952 // one if ro.product.cpu.abi2 is defined.
2953 //
2954 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2955 File dataPath, File scanFile) {
2956 final String cpuAbi = Build.CPU_ABI;
2957 try {
2958 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
2959
2960 // some architectures are capable of supporting several CPU ABIs
2961 // for example, 'armeabi-v7a' also supports 'armeabi' native code
2962 // this is indicated by the definition of the ro.product.cpu.abi2
2963 // system property.
2964 //
2965 // only scan the package twice in case of ABI mismatch
2966 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2967 String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
2968 if (cpuAbi2 != null) {
2969 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002971
2972 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2973 Log.w(TAG,"Native ABI mismatch from package file");
2974 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 }
2976 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002977 } catch (ZipException e) {
2978 Log.w(TAG, "Failed to extract data from package file", e);
2979 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002980 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002981 Log.w(TAG, "Failed to cache package shared libs", e);
2982 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002983 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002984 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
2986
2987 private void cacheSharedLibLI(PackageParser.Package pkg,
2988 ZipFile zipFile, ZipEntry entry,
2989 File sharedLibraryDir,
2990 File sharedLibraryFile) throws IOException {
2991 InputStream inputStream = zipFile.getInputStream(entry);
2992 try {
2993 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2994 String tempFilePath = tempFile.getPath();
2995 // XXX package manager can't change owner, so the lib files for
2996 // now need to be left as world readable and owned by the system.
2997 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2998 ! tempFile.setLastModified(entry.getTime()) ||
2999 FileUtils.setPermissions(tempFilePath,
3000 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
3001 |FileUtils.S_IROTH, -1, -1) != 0 ||
3002 ! tempFile.renameTo(sharedLibraryFile)) {
3003 // Failed to properly write file.
3004 tempFile.delete();
3005 throw new IOException("Couldn't create cached shared lib "
3006 + sharedLibraryFile + " in " + sharedLibraryDir);
3007 }
3008 } finally {
3009 inputStream.close();
3010 }
3011 }
3012
3013 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3014 if (chatty && Config.LOGD) Log.d(
3015 TAG, "Removing package " + pkg.applicationInfo.packageName );
3016
3017 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003020 mPackages.remove(pkg.applicationInfo.packageName);
3021 if (pkg.mPath != null) {
3022 mAppDirs.remove(pkg.mPath);
3023 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003025 PackageSetting ps = (PackageSetting)pkg.mExtras;
3026 if (ps != null && ps.sharedUser != null) {
3027 // XXX don't do this until the data is removed.
3028 if (false) {
3029 ps.sharedUser.packages.remove(ps);
3030 if (ps.sharedUser.packages.size() == 0) {
3031 // Remove.
3032 }
3033 }
3034 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 int N = pkg.providers.size();
3037 StringBuilder r = null;
3038 int i;
3039 for (i=0; i<N; i++) {
3040 PackageParser.Provider p = pkg.providers.get(i);
3041 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3042 p.info.name));
3043 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 /* The is another ContentProvider with this authority when
3046 * this app was installed so this authority is null,
3047 * Ignore it as we don't have to unregister the provider.
3048 */
3049 continue;
3050 }
3051 String names[] = p.info.authority.split(";");
3052 for (int j = 0; j < names.length; j++) {
3053 if (mProviders.get(names[j]) == p) {
3054 mProviders.remove(names[j]);
3055 if (chatty && Config.LOGD) Log.d(
3056 TAG, "Unregistered content provider: " + names[j] +
3057 ", className = " + p.info.name +
3058 ", isSyncable = " + p.info.isSyncable);
3059 }
3060 }
3061 if (chatty) {
3062 if (r == null) {
3063 r = new StringBuilder(256);
3064 } else {
3065 r.append(' ');
3066 }
3067 r.append(p.info.name);
3068 }
3069 }
3070 if (r != null) {
3071 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 N = pkg.services.size();
3075 r = null;
3076 for (i=0; i<N; i++) {
3077 PackageParser.Service s = pkg.services.get(i);
3078 mServices.removeService(s);
3079 if (chatty) {
3080 if (r == null) {
3081 r = new StringBuilder(256);
3082 } else {
3083 r.append(' ');
3084 }
3085 r.append(s.info.name);
3086 }
3087 }
3088 if (r != null) {
3089 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3090 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 N = pkg.receivers.size();
3093 r = null;
3094 for (i=0; i<N; i++) {
3095 PackageParser.Activity a = pkg.receivers.get(i);
3096 mReceivers.removeActivity(a, "receiver");
3097 if (chatty) {
3098 if (r == null) {
3099 r = new StringBuilder(256);
3100 } else {
3101 r.append(' ');
3102 }
3103 r.append(a.info.name);
3104 }
3105 }
3106 if (r != null) {
3107 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3108 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 N = pkg.activities.size();
3111 r = null;
3112 for (i=0; i<N; i++) {
3113 PackageParser.Activity a = pkg.activities.get(i);
3114 mActivities.removeActivity(a, "activity");
3115 if (chatty) {
3116 if (r == null) {
3117 r = new StringBuilder(256);
3118 } else {
3119 r.append(' ');
3120 }
3121 r.append(a.info.name);
3122 }
3123 }
3124 if (r != null) {
3125 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3126 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003128 N = pkg.permissions.size();
3129 r = null;
3130 for (i=0; i<N; i++) {
3131 PackageParser.Permission p = pkg.permissions.get(i);
3132 boolean tree = false;
3133 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3134 if (bp == null) {
3135 tree = true;
3136 bp = mSettings.mPermissionTrees.get(p.info.name);
3137 }
3138 if (bp != null && bp.perm == p) {
3139 if (bp.type != BasePermission.TYPE_BUILTIN) {
3140 if (tree) {
3141 mSettings.mPermissionTrees.remove(p.info.name);
3142 } else {
3143 mSettings.mPermissions.remove(p.info.name);
3144 }
3145 } else {
3146 bp.perm = null;
3147 }
3148 if (chatty) {
3149 if (r == null) {
3150 r = new StringBuilder(256);
3151 } else {
3152 r.append(' ');
3153 }
3154 r.append(p.info.name);
3155 }
3156 }
3157 }
3158 if (r != null) {
3159 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3160 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 N = pkg.instrumentation.size();
3163 r = null;
3164 for (i=0; i<N; i++) {
3165 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3166 mInstrumentation.remove(a.component);
3167 if (chatty) {
3168 if (r == null) {
3169 r = new StringBuilder(256);
3170 } else {
3171 r.append(' ');
3172 }
3173 r.append(a.info.name);
3174 }
3175 }
3176 if (r != null) {
3177 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3178 }
3179 }
3180 }
3181
3182 private static final boolean isPackageFilename(String name) {
3183 return name != null && name.endsWith(".apk");
3184 }
3185
3186 private void updatePermissionsLP() {
3187 // Make sure there are no dangling permission trees.
3188 Iterator<BasePermission> it = mSettings.mPermissionTrees
3189 .values().iterator();
3190 while (it.hasNext()) {
3191 BasePermission bp = it.next();
3192 if (bp.perm == null) {
3193 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3194 + " from package " + bp.sourcePackage);
3195 it.remove();
3196 }
3197 }
3198
3199 // Make sure all dynamic permissions have been assigned to a package,
3200 // and make sure there are no dangling permissions.
3201 it = mSettings.mPermissions.values().iterator();
3202 while (it.hasNext()) {
3203 BasePermission bp = it.next();
3204 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3205 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3206 + bp.name + " pkg=" + bp.sourcePackage
3207 + " info=" + bp.pendingInfo);
3208 if (bp.perm == null && bp.pendingInfo != null) {
3209 BasePermission tree = findPermissionTreeLP(bp.name);
3210 if (tree != null) {
3211 bp.perm = new PackageParser.Permission(tree.perm.owner,
3212 new PermissionInfo(bp.pendingInfo));
3213 bp.perm.info.packageName = tree.perm.info.packageName;
3214 bp.perm.info.name = bp.name;
3215 bp.uid = tree.uid;
3216 }
3217 }
3218 }
3219 if (bp.perm == null) {
3220 Log.w(TAG, "Removing dangling permission: " + bp.name
3221 + " from package " + bp.sourcePackage);
3222 it.remove();
3223 }
3224 }
3225
3226 // Now update the permissions for all packages, in particular
3227 // replace the granted permissions of the system packages.
3228 for (PackageParser.Package pkg : mPackages.values()) {
3229 grantPermissionsLP(pkg, false);
3230 }
3231 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003233 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3234 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3235 if (ps == null) {
3236 return;
3237 }
3238 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3239 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003241 if (replace) {
3242 ps.permissionsFixed = false;
3243 if (gp == ps) {
3244 gp.grantedPermissions.clear();
3245 gp.gids = mGlobalGids;
3246 }
3247 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 if (gp.gids == null) {
3250 gp.gids = mGlobalGids;
3251 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 final int N = pkg.requestedPermissions.size();
3254 for (int i=0; i<N; i++) {
3255 String name = pkg.requestedPermissions.get(i);
3256 BasePermission bp = mSettings.mPermissions.get(name);
3257 PackageParser.Permission p = bp != null ? bp.perm : null;
3258 if (false) {
3259 if (gp != ps) {
3260 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3261 + ": " + p);
3262 }
3263 }
3264 if (p != null) {
3265 final String perm = p.info.name;
3266 boolean allowed;
3267 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3268 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3269 allowed = true;
3270 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3271 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003272 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003274 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003275 == PackageManager.SIGNATURE_MATCH);
3276 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3277 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3278 // For updated system applications, the signatureOrSystem permission
3279 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003280 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3282 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3283 if(sysPs.grantedPermissions.contains(perm)) {
3284 allowed = true;
3285 } else {
3286 allowed = false;
3287 }
3288 } else {
3289 allowed = true;
3290 }
3291 }
3292 }
3293 } else {
3294 allowed = false;
3295 }
3296 if (false) {
3297 if (gp != ps) {
3298 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3299 }
3300 }
3301 if (allowed) {
3302 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3303 && ps.permissionsFixed) {
3304 // If this is an existing, non-system package, then
3305 // we can't add any new permissions to it.
3306 if (!gp.loadedPermissions.contains(perm)) {
3307 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003308 // Except... if this is a permission that was added
3309 // to the platform (note: need to only do this when
3310 // updating the platform).
3311 final int NP = PackageParser.NEW_PERMISSIONS.length;
3312 for (int ip=0; ip<NP; ip++) {
3313 final PackageParser.NewPermissionInfo npi
3314 = PackageParser.NEW_PERMISSIONS[ip];
3315 if (npi.name.equals(perm)
3316 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3317 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003318 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003319 + pkg.packageName);
3320 break;
3321 }
3322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003323 }
3324 }
3325 if (allowed) {
3326 if (!gp.grantedPermissions.contains(perm)) {
3327 addedPermission = true;
3328 gp.grantedPermissions.add(perm);
3329 gp.gids = appendInts(gp.gids, bp.gids);
3330 }
3331 } else {
3332 Log.w(TAG, "Not granting permission " + perm
3333 + " to package " + pkg.packageName
3334 + " because it was previously installed without");
3335 }
3336 } else {
3337 Log.w(TAG, "Not granting permission " + perm
3338 + " to package " + pkg.packageName
3339 + " (protectionLevel=" + p.info.protectionLevel
3340 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3341 + ")");
3342 }
3343 } else {
3344 Log.w(TAG, "Unknown permission " + name
3345 + " in package " + pkg.packageName);
3346 }
3347 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003349 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003350 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3351 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 // This is the first that we have heard about this package, so the
3353 // permissions we have now selected are fixed until explicitly
3354 // changed.
3355 ps.permissionsFixed = true;
3356 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3357 }
3358 }
3359
3360 private final class ActivityIntentResolver
3361 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003362 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003364 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003365 }
3366
Mihai Preda074edef2009-05-18 17:13:31 +02003367 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003368 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003369 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3371 }
3372
Mihai Predaeae850c2009-05-13 10:13:48 +02003373 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3374 ArrayList<PackageParser.Activity> packageActivities) {
3375 if (packageActivities == null) {
3376 return null;
3377 }
3378 mFlags = flags;
3379 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3380 int N = packageActivities.size();
3381 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3382 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003383
3384 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003385 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003386 intentFilters = packageActivities.get(i).intents;
3387 if (intentFilters != null && intentFilters.size() > 0) {
3388 listCut.add(intentFilters);
3389 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003390 }
3391 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3392 }
3393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 public final void addActivity(PackageParser.Activity a, String type) {
3395 mActivities.put(a.component, a);
3396 if (SHOW_INFO || Config.LOGV) Log.v(
3397 TAG, " " + type + " " +
3398 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3399 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3400 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003401 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3403 if (SHOW_INFO || Config.LOGV) {
3404 Log.v(TAG, " IntentFilter:");
3405 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3406 }
3407 if (!intent.debugCheck()) {
3408 Log.w(TAG, "==> For Activity " + a.info.name);
3409 }
3410 addFilter(intent);
3411 }
3412 }
3413
3414 public final void removeActivity(PackageParser.Activity a, String type) {
3415 mActivities.remove(a.component);
3416 if (SHOW_INFO || Config.LOGV) Log.v(
3417 TAG, " " + type + " " +
3418 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3419 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3420 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003421 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003422 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3423 if (SHOW_INFO || Config.LOGV) {
3424 Log.v(TAG, " IntentFilter:");
3425 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3426 }
3427 removeFilter(intent);
3428 }
3429 }
3430
3431 @Override
3432 protected boolean allowFilterResult(
3433 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3434 ActivityInfo filterAi = filter.activity.info;
3435 for (int i=dest.size()-1; i>=0; i--) {
3436 ActivityInfo destAi = dest.get(i).activityInfo;
3437 if (destAi.name == filterAi.name
3438 && destAi.packageName == filterAi.packageName) {
3439 return false;
3440 }
3441 }
3442 return true;
3443 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 @Override
3446 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3447 int match) {
3448 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3449 return null;
3450 }
3451 final PackageParser.Activity activity = info.activity;
3452 if (mSafeMode && (activity.info.applicationInfo.flags
3453 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3454 return null;
3455 }
3456 final ResolveInfo res = new ResolveInfo();
3457 res.activityInfo = PackageParser.generateActivityInfo(activity,
3458 mFlags);
3459 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3460 res.filter = info;
3461 }
3462 res.priority = info.getPriority();
3463 res.preferredOrder = activity.owner.mPreferredOrder;
3464 //System.out.println("Result: " + res.activityInfo.className +
3465 // " = " + res.priority);
3466 res.match = match;
3467 res.isDefault = info.hasDefault;
3468 res.labelRes = info.labelRes;
3469 res.nonLocalizedLabel = info.nonLocalizedLabel;
3470 res.icon = info.icon;
3471 return res;
3472 }
3473
3474 @Override
3475 protected void sortResults(List<ResolveInfo> results) {
3476 Collections.sort(results, mResolvePrioritySorter);
3477 }
3478
3479 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003480 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003481 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003482 out.print(prefix); out.print(
3483 Integer.toHexString(System.identityHashCode(filter.activity)));
3484 out.print(' ');
3485 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 }
3487
3488// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3489// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3490// final List<ResolveInfo> retList = Lists.newArrayList();
3491// while (i.hasNext()) {
3492// final ResolveInfo resolveInfo = i.next();
3493// if (isEnabledLP(resolveInfo.activityInfo)) {
3494// retList.add(resolveInfo);
3495// }
3496// }
3497// return retList;
3498// }
3499
3500 // Keys are String (activity class name), values are Activity.
3501 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3502 = new HashMap<ComponentName, PackageParser.Activity>();
3503 private int mFlags;
3504 }
3505
3506 private final class ServiceIntentResolver
3507 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003508 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003510 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 }
3512
Mihai Preda074edef2009-05-18 17:13:31 +02003513 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003515 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003516 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3517 }
3518
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003519 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3520 ArrayList<PackageParser.Service> packageServices) {
3521 if (packageServices == null) {
3522 return null;
3523 }
3524 mFlags = flags;
3525 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3526 int N = packageServices.size();
3527 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3528 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3529
3530 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3531 for (int i = 0; i < N; ++i) {
3532 intentFilters = packageServices.get(i).intents;
3533 if (intentFilters != null && intentFilters.size() > 0) {
3534 listCut.add(intentFilters);
3535 }
3536 }
3537 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3538 }
3539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 public final void addService(PackageParser.Service s) {
3541 mServices.put(s.component, s);
3542 if (SHOW_INFO || Config.LOGV) Log.v(
3543 TAG, " " + (s.info.nonLocalizedLabel != null
3544 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3545 if (SHOW_INFO || Config.LOGV) Log.v(
3546 TAG, " Class=" + s.info.name);
3547 int NI = s.intents.size();
3548 int j;
3549 for (j=0; j<NI; j++) {
3550 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3551 if (SHOW_INFO || Config.LOGV) {
3552 Log.v(TAG, " IntentFilter:");
3553 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3554 }
3555 if (!intent.debugCheck()) {
3556 Log.w(TAG, "==> For Service " + s.info.name);
3557 }
3558 addFilter(intent);
3559 }
3560 }
3561
3562 public final void removeService(PackageParser.Service s) {
3563 mServices.remove(s.component);
3564 if (SHOW_INFO || Config.LOGV) Log.v(
3565 TAG, " " + (s.info.nonLocalizedLabel != null
3566 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3567 if (SHOW_INFO || Config.LOGV) Log.v(
3568 TAG, " Class=" + s.info.name);
3569 int NI = s.intents.size();
3570 int j;
3571 for (j=0; j<NI; j++) {
3572 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3573 if (SHOW_INFO || Config.LOGV) {
3574 Log.v(TAG, " IntentFilter:");
3575 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3576 }
3577 removeFilter(intent);
3578 }
3579 }
3580
3581 @Override
3582 protected boolean allowFilterResult(
3583 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3584 ServiceInfo filterSi = filter.service.info;
3585 for (int i=dest.size()-1; i>=0; i--) {
3586 ServiceInfo destAi = dest.get(i).serviceInfo;
3587 if (destAi.name == filterSi.name
3588 && destAi.packageName == filterSi.packageName) {
3589 return false;
3590 }
3591 }
3592 return true;
3593 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003595 @Override
3596 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3597 int match) {
3598 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3599 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3600 return null;
3601 }
3602 final PackageParser.Service service = info.service;
3603 if (mSafeMode && (service.info.applicationInfo.flags
3604 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3605 return null;
3606 }
3607 final ResolveInfo res = new ResolveInfo();
3608 res.serviceInfo = PackageParser.generateServiceInfo(service,
3609 mFlags);
3610 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3611 res.filter = filter;
3612 }
3613 res.priority = info.getPriority();
3614 res.preferredOrder = service.owner.mPreferredOrder;
3615 //System.out.println("Result: " + res.activityInfo.className +
3616 // " = " + res.priority);
3617 res.match = match;
3618 res.isDefault = info.hasDefault;
3619 res.labelRes = info.labelRes;
3620 res.nonLocalizedLabel = info.nonLocalizedLabel;
3621 res.icon = info.icon;
3622 return res;
3623 }
3624
3625 @Override
3626 protected void sortResults(List<ResolveInfo> results) {
3627 Collections.sort(results, mResolvePrioritySorter);
3628 }
3629
3630 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003631 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003633 out.print(prefix); out.print(
3634 Integer.toHexString(System.identityHashCode(filter.service)));
3635 out.print(' ');
3636 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003637 }
3638
3639// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3640// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3641// final List<ResolveInfo> retList = Lists.newArrayList();
3642// while (i.hasNext()) {
3643// final ResolveInfo resolveInfo = (ResolveInfo) i;
3644// if (isEnabledLP(resolveInfo.serviceInfo)) {
3645// retList.add(resolveInfo);
3646// }
3647// }
3648// return retList;
3649// }
3650
3651 // Keys are String (activity class name), values are Activity.
3652 private final HashMap<ComponentName, PackageParser.Service> mServices
3653 = new HashMap<ComponentName, PackageParser.Service>();
3654 private int mFlags;
3655 };
3656
3657 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3658 new Comparator<ResolveInfo>() {
3659 public int compare(ResolveInfo r1, ResolveInfo r2) {
3660 int v1 = r1.priority;
3661 int v2 = r2.priority;
3662 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3663 if (v1 != v2) {
3664 return (v1 > v2) ? -1 : 1;
3665 }
3666 v1 = r1.preferredOrder;
3667 v2 = r2.preferredOrder;
3668 if (v1 != v2) {
3669 return (v1 > v2) ? -1 : 1;
3670 }
3671 if (r1.isDefault != r2.isDefault) {
3672 return r1.isDefault ? -1 : 1;
3673 }
3674 v1 = r1.match;
3675 v2 = r2.match;
3676 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3677 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3678 }
3679 };
3680
3681 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3682 new Comparator<ProviderInfo>() {
3683 public int compare(ProviderInfo p1, ProviderInfo p2) {
3684 final int v1 = p1.initOrder;
3685 final int v2 = p2.initOrder;
3686 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3687 }
3688 };
3689
3690 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3691 IActivityManager am = ActivityManagerNative.getDefault();
3692 if (am != null) {
3693 try {
3694 final Intent intent = new Intent(action,
3695 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3696 if (extras != null) {
3697 intent.putExtras(extras);
3698 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003699 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003700 am.broadcastIntent(
3701 null, intent,
3702 null, null, 0, null, null, null, false, false);
3703 } catch (RemoteException ex) {
3704 }
3705 }
3706 }
3707
3708 private final class AppDirObserver extends FileObserver {
3709 public AppDirObserver(String path, int mask, boolean isrom) {
3710 super(path, mask);
3711 mRootDir = path;
3712 mIsRom = isrom;
3713 }
3714
3715 public void onEvent(int event, String path) {
3716 String removedPackage = null;
3717 int removedUid = -1;
3718 String addedPackage = null;
3719 int addedUid = -1;
3720
3721 synchronized (mInstallLock) {
3722 String fullPathStr = null;
3723 File fullPath = null;
3724 if (path != null) {
3725 fullPath = new File(mRootDir, path);
3726 fullPathStr = fullPath.getPath();
3727 }
3728
3729 if (Config.LOGV) Log.v(
3730 TAG, "File " + fullPathStr + " changed: "
3731 + Integer.toHexString(event));
3732
3733 if (!isPackageFilename(path)) {
3734 if (Config.LOGV) Log.v(
3735 TAG, "Ignoring change of non-package file: " + fullPathStr);
3736 return;
3737 }
3738
3739 if ((event&REMOVE_EVENTS) != 0) {
3740 synchronized (mInstallLock) {
3741 PackageParser.Package p = mAppDirs.get(fullPathStr);
3742 if (p != null) {
3743 removePackageLI(p, true);
3744 removedPackage = p.applicationInfo.packageName;
3745 removedUid = p.applicationInfo.uid;
3746 }
3747 }
3748 }
3749
3750 if ((event&ADD_EVENTS) != 0) {
3751 PackageParser.Package p = mAppDirs.get(fullPathStr);
3752 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003753 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3755 PackageParser.PARSE_CHATTY |
3756 PackageParser.PARSE_MUST_BE_APK,
3757 SCAN_MONITOR);
3758 if (p != null) {
3759 synchronized (mPackages) {
3760 grantPermissionsLP(p, false);
3761 }
3762 addedPackage = p.applicationInfo.packageName;
3763 addedUid = p.applicationInfo.uid;
3764 }
3765 }
3766 }
3767
3768 synchronized (mPackages) {
3769 mSettings.writeLP();
3770 }
3771 }
3772
3773 if (removedPackage != null) {
3774 Bundle extras = new Bundle(1);
3775 extras.putInt(Intent.EXTRA_UID, removedUid);
3776 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3777 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3778 }
3779 if (addedPackage != null) {
3780 Bundle extras = new Bundle(1);
3781 extras.putInt(Intent.EXTRA_UID, addedUid);
3782 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3783 }
3784 }
3785
3786 private final String mRootDir;
3787 private final boolean mIsRom;
3788 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 /* Called when a downloaded package installation has been confirmed by the user */
3791 public void installPackage(
3792 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003793 installPackage(packageURI, observer, flags, null);
3794 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003795
Jacek Surazski65e13172009-04-28 15:26:38 +02003796 /* Called when a downloaded package installation has been confirmed by the user */
3797 public void installPackage(
3798 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3799 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 mContext.enforceCallingOrSelfPermission(
3801 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 // Queue up an async operation since the package installation may take a little while.
3804 mHandler.post(new Runnable() {
3805 public void run() {
3806 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003807 // Result object to be returned
3808 PackageInstalledInfo res = new PackageInstalledInfo();
3809 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3810 res.uid = -1;
3811 res.pkg = null;
3812 res.removedInfo = new PackageRemovedInfo();
3813 // Make a temporary copy of file from given packageURI
3814 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3815 if (tmpPackageFile != null) {
3816 synchronized (mInstallLock) {
3817 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3818 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 }
3820 if (observer != null) {
3821 try {
3822 observer.packageInstalled(res.name, res.returnCode);
3823 } catch (RemoteException e) {
3824 Log.i(TAG, "Observer no longer exists.");
3825 }
3826 }
3827 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3828 // call appears in the synchronized block above.
3829 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3830 res.removedInfo.sendBroadcast(false, true);
3831 Bundle extras = new Bundle(1);
3832 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003833 final boolean update = res.removedInfo.removedPackage != null;
3834 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3836 }
3837 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3838 res.pkg.applicationInfo.packageName,
3839 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003840 if (update) {
3841 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3842 res.pkg.applicationInfo.packageName,
3843 extras);
3844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 }
3846 Runtime.getRuntime().gc();
3847 }
3848 });
3849 }
3850
3851 class PackageInstalledInfo {
3852 String name;
3853 int uid;
3854 PackageParser.Package pkg;
3855 int returnCode;
3856 PackageRemovedInfo removedInfo;
3857 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 /*
3860 * Install a non-existing package.
3861 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003862 private void installNewPackageLI(PackageParser.Package pkg,
3863 int parseFlags,
3864 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02003865 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08003867 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003868 String pkgName = pkg.packageName;
3869 boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
Oscar Montemayora8529f62009-11-18 10:14:20 -08003870
3871 if (useEncryptedFilesystemForPackage(pkg)) {
3872 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
3873 } else {
3874 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 res.name = pkgName;
3877 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003878 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003879 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003880 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003881 + " without first uninstalling.");
3882 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3883 return;
3884 }
3885 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003886 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003887 if (onSd) {
3888 // Create secure container mount point for package
3889 String cPath = createSdDir(new File(pkg.mScanPath), pkgName);
3890 if (cPath == null) {
3891 mLastScanError = res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
3892 return;
3893 }
3894 }
3895 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003897 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3899 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3900 }
3901 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003902 File destPackageFile = new File(pkg.mPath);
3903 if (destPackageFile.exists()) {
3904 // It's safe to do this because we know (from the above check) that the file
3905 // isn't currently used for an installed package.
3906 destPackageFile.delete();
3907 }
3908 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02003909 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 res);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003911 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3912 // Check if container can be finalized
3913 if(onSd && !finalizeSdDir(pkgName)) {
3914 res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
3915 }
3916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 // delete the partially installed application. the data directory will have to be
3918 // restored if it was already existing
3919 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3920 // remove package from internal structures. Note that we want deletePackageX to
3921 // delete the package data and cache directories that it created in
3922 // scanPackageLocked, unless those directories existed before we even tried to
3923 // install.
3924 deletePackageLI(
3925 pkgName, true,
3926 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3927 res.removedInfo);
3928 }
3929 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003930 if (onSd && res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3931 // Destroy cache
3932 destroySdDir(pkgName);
3933 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003935
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003936 private void replacePackageLI(PackageParser.Package pkg,
3937 int parseFlags,
3938 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02003939 String installerPackageName, PackageInstalledInfo res) {
3940
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003941 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003942 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 // First find the old package info and check signatures
3944 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003945 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003946 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3947 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3949 return;
3950 }
3951 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003952 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 if(sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003954 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003956 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 }
3958 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003961 PackageParser.Package pkg,
3962 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02003963 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 PackageParser.Package newPackage = null;
3965 String pkgName = deletedPackage.packageName;
3966 boolean deletedPkg = true;
3967 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003968
Jacek Surazski65e13172009-04-28 15:26:38 +02003969 String oldInstallerPackageName = null;
3970 synchronized (mPackages) {
3971 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3972 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003973
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003974 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 // First delete the existing package while retaining the data directory
3976 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3977 res.removedInfo)) {
3978 // If the existing package was'nt successfully deleted
3979 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3980 deletedPkg = false;
3981 } else {
3982 // Successfully deleted the old package. Now proceed with re-installation
3983 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003984 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003985 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003986 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3988 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08003989 }
3990 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003991 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02003992 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 res);
3994 updatedSettings = true;
3995 }
3996 }
3997
3998 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3999 // If we deleted an exisiting package, the old source and resource files that we
4000 // were keeping around in case we needed them (see below) can now be deleted
4001 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
4002 final ApplicationInfo installedPackageAppInfo =
4003 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004004 deletePackageResourcesLI(pkgName,
4005 !deletedPackageAppInfo.sourceDir
4006 .equals(installedPackageAppInfo.sourceDir)
4007 ? deletedPackageAppInfo.sourceDir : null,
4008 !deletedPackageAppInfo.publicSourceDir
4009 .equals(installedPackageAppInfo.publicSourceDir)
4010 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 //update signature on the new package setting
4012 //this should always succeed, since we checked the
4013 //signature earlier.
4014 synchronized(mPackages) {
4015 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4016 parseFlags, true);
4017 }
4018 } else {
4019 // remove package from internal structures. Note that we want deletePackageX to
4020 // delete the package data and cache directories that it created in
4021 // scanPackageLocked, unless those directories existed before we even tried to
4022 // install.
4023 if(updatedSettings) {
4024 deletePackageLI(
4025 pkgName, true,
4026 PackageManager.DONT_DELETE_DATA,
4027 res.removedInfo);
4028 }
4029 // Since we failed to install the new package we need to restore the old
4030 // package that we deleted.
4031 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004032 File restoreFile = new File(deletedPackage.mPath);
4033 if (restoreFile == null) {
4034 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4035 return;
4036 }
4037 File restoreTmpFile = createTempPackageFile();
4038 if (restoreTmpFile == null) {
4039 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
4040 return;
4041 }
4042 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
4043 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
4044 return;
4045 }
4046 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4047 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004049 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004051 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004052 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
4053 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4054 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056 }
4057 }
4058 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004061 PackageParser.Package pkg,
4062 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004063 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 PackageParser.Package newPackage = null;
4065 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004066 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 PackageParser.PARSE_IS_SYSTEM;
4068 String packageName = deletedPackage.packageName;
4069 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4070 if (packageName == null) {
4071 Log.w(TAG, "Attempt to delete null packageName.");
4072 return;
4073 }
4074 PackageParser.Package oldPkg;
4075 PackageSetting oldPkgSetting;
4076 synchronized (mPackages) {
4077 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004078 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4080 (oldPkgSetting == null)) {
4081 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4082 return;
4083 }
4084 }
4085 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4086 res.removedInfo.removedPackage = packageName;
4087 // Remove existing system package
4088 removePackageLI(oldPkg, true);
4089 synchronized (mPackages) {
4090 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4091 }
4092
4093 // Successfully disabled the old package. Now proceed with re-installation
4094 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4095 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004096 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004098 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4100 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4101 }
4102 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004103 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 updatedSettings = true;
4105 }
4106
4107 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4108 //update signature on the new package setting
4109 //this should always succeed, since we checked the
4110 //signature earlier.
4111 synchronized(mPackages) {
4112 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4113 parseFlags, true);
4114 }
4115 } else {
4116 // Re installation failed. Restore old information
4117 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004118 if (newPackage != null) {
4119 removePackageLI(newPackage, true);
4120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004121 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004122 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004124 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004125 // Restore the old system information in Settings
4126 synchronized(mPackages) {
4127 if(updatedSettings) {
4128 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004129 mSettings.setInstallerPackageName(packageName,
4130 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 }
4132 mSettings.writeLP();
4133 }
4134 }
4135 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004136
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004137 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004138 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004139 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 synchronized (mPackages) {
4141 //write settings. the installStatus will be incomplete at this stage.
4142 //note that the new package setting would have already been
4143 //added to mPackages. It hasn't been persisted yet.
4144 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4145 mSettings.writeLP();
4146 }
4147
4148 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004149 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4150 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004151 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004152 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004153 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4154 return;
4155 }
4156 }
4157 // XXX There are probably some big issues here: upon doing
4158 // the rename, we have reached the point of no return (the
4159 // original .apk is gone!), so we can't fail. Yet... we can.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004160 File scanFile = new File(newPackage.mScanPath);
4161 if (!scanFile.renameTo(new File(newPackage.mPath))) {
4162 Log.e(TAG, "Couldn't move package file: " + newPackage.mScanPath + " to: " + newPackage.mPath);
4163 // TODO rename should work. Workaround
4164 if (!FileUtils.copyFile(scanFile, new File(newPackage.mPath))) {
4165 Log.e(TAG, "Couldn't move package file to: " + newPackage.mPath);
4166 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004168 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004169 res.returnCode = setPermissionsLI(newPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4171 return;
4172 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004173 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 }
4175 }
4176 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4177 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004178 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 }
4180 }
4181
4182 synchronized (mPackages) {
4183 grantPermissionsLP(newPackage, true);
4184 res.name = pkgName;
4185 res.uid = newPackage.applicationInfo.uid;
4186 res.pkg = newPackage;
4187 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004188 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4190 //to update install status
4191 mSettings.writeLP();
4192 }
4193 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004194
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004195 private File copyTempInstallFile(Uri pPackageURI,
4196 PackageInstalledInfo res) {
4197 File tmpPackageFile = createTempPackageFile();
4198 int retCode = PackageManager.INSTALL_SUCCEEDED;
4199 if (tmpPackageFile == null) {
4200 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4201 return null;
4202 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004203
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004204 if (pPackageURI.getScheme().equals("file")) {
4205 final File srcPackageFile = new File(pPackageURI.getPath());
4206 // We copy the source package file to a temp file and then rename it to the
4207 // destination file in order to eliminate a window where the package directory
4208 // scanner notices the new package file but it's not completely copied yet.
4209 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4210 Log.e(TAG, "Couldn't copy package file to temp file.");
4211 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004213 } else if (pPackageURI.getScheme().equals("content")) {
4214 ParcelFileDescriptor fd = null;
4215 try {
4216 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4217 } catch (FileNotFoundException e) {
4218 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4219 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4220 }
4221 if (fd == null) {
4222 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4223 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4224 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004225 if (Config.LOGV) {
4226 Log.v(TAG, "Opened file descriptor from download service.");
4227 }
4228 ParcelFileDescriptor.AutoCloseInputStream
4229 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4230 // We copy the source package file to a temp file and then rename it to the
4231 // destination file in order to eliminate a window where the package directory
4232 // scanner notices the new package file but it's not completely copied yet.
4233 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4234 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004235 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004238 } else {
4239 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4240 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4241 }
4242
4243 res.returnCode = retCode;
4244 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4245 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4246 tmpPackageFile.delete();
4247 }
4248 return null;
4249 }
4250 return tmpPackageFile;
4251 }
4252
4253 private void installPackageLI(Uri pPackageURI,
4254 int pFlags, boolean newInstall, String installerPackageName,
4255 File tmpPackageFile, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004256 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
4257 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004258 boolean replacingExistingPackage = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004259 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
4260 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004261 // Result object to be returned
4262 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4263
4264 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 // Retrieve PackageSettings and parse package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004266 int parseFlags = PackageParser.PARSE_CHATTY |
4267 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
4268 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269 parseFlags |= mDefParseFlags;
4270 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4271 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004273 null, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 if (pkg == null) {
4275 res.returnCode = pp.getParseError();
4276 break main_flow;
4277 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004278 String pkgName = res.name = pkg.packageName;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004279 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4280 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4281 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4282 break main_flow;
4283 }
4284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004285 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4286 res.returnCode = pp.getParseError();
4287 break main_flow;
4288 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 synchronized (mPackages) {
4291 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004292 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 && mPackages.containsKey(pkgName)) {
4294 replacingExistingPackage = true;
4295 }
4296 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004298 if(replacingExistingPackage) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004299 replacePackageLI(pkg, parseFlags, scanMode,
4300 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004302 installNewPackageLI(pkg, parseFlags, scanMode,
4303 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004304 }
4305 } finally {
4306 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4307 tmpPackageFile.delete();
4308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004309 }
4310 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004311
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004312 private int setPermissionsLI(PackageParser.Package newPackage) {
4313 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 int retCode;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004315 if ((newPackage.applicationInfo.flags
4316 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
4317 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318 try {
4319 extractPublicFiles(newPackage, destResourceFile);
4320 } catch (IOException e) {
4321 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4322 " forward-locked app.");
4323 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4324 } finally {
4325 //TODO clean up the extracted public files
4326 }
4327 if (mInstaller != null) {
4328 retCode = mInstaller.setForwardLockPerm(pkgName,
4329 newPackage.applicationInfo.uid);
4330 } else {
4331 final int filePermissions =
4332 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004333 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334 newPackage.applicationInfo.uid);
4335 }
4336 } else {
4337 final int filePermissions =
4338 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4339 |FileUtils.S_IROTH;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004340 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 }
4342 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004343 Log.e(TAG, "Couldn't set new package file permissions for " +
4344 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004345 + ". The return code was: " + retCode);
4346 }
4347 return PackageManager.INSTALL_SUCCEEDED;
4348 }
4349
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004350 private boolean isForwardLocked(PackageParser.Package pkg) {
4351 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 }
4353
4354 private void extractPublicFiles(PackageParser.Package newPackage,
4355 File publicZipFile) throws IOException {
4356 final ZipOutputStream publicZipOutStream =
4357 new ZipOutputStream(new FileOutputStream(publicZipFile));
4358 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4359
4360 // Copy manifest, resources.arsc and res directory to public zip
4361
4362 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4363 while (privateZipEntries.hasMoreElements()) {
4364 final ZipEntry zipEntry = privateZipEntries.nextElement();
4365 final String zipEntryName = zipEntry.getName();
4366 if ("AndroidManifest.xml".equals(zipEntryName)
4367 || "resources.arsc".equals(zipEntryName)
4368 || zipEntryName.startsWith("res/")) {
4369 try {
4370 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4371 } catch (IOException e) {
4372 try {
4373 publicZipOutStream.close();
4374 throw e;
4375 } finally {
4376 publicZipFile.delete();
4377 }
4378 }
4379 }
4380 }
4381
4382 publicZipOutStream.close();
4383 FileUtils.setPermissions(
4384 publicZipFile.getAbsolutePath(),
4385 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4386 -1, -1);
4387 }
4388
4389 private static void copyZipEntry(ZipEntry zipEntry,
4390 ZipFile inZipFile,
4391 ZipOutputStream outZipStream) throws IOException {
4392 byte[] buffer = new byte[4096];
4393 int num;
4394
4395 ZipEntry newEntry;
4396 if (zipEntry.getMethod() == ZipEntry.STORED) {
4397 // Preserve the STORED method of the input entry.
4398 newEntry = new ZipEntry(zipEntry);
4399 } else {
4400 // Create a new entry so that the compressed len is recomputed.
4401 newEntry = new ZipEntry(zipEntry.getName());
4402 }
4403 outZipStream.putNextEntry(newEntry);
4404
4405 InputStream data = inZipFile.getInputStream(zipEntry);
4406 while ((num = data.read(buffer)) > 0) {
4407 outZipStream.write(buffer, 0, num);
4408 }
4409 outZipStream.flush();
4410 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 private void deleteTempPackageFiles() {
4413 FilenameFilter filter = new FilenameFilter() {
4414 public boolean accept(File dir, String name) {
4415 return name.startsWith("vmdl") && name.endsWith(".tmp");
4416 }
4417 };
4418 String tmpFilesList[] = mAppInstallDir.list(filter);
4419 if(tmpFilesList == null) {
4420 return;
4421 }
4422 for(int i = 0; i < tmpFilesList.length; i++) {
4423 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4424 tmpFile.delete();
4425 }
4426 }
4427
4428 private File createTempPackageFile() {
4429 File tmpPackageFile;
4430 try {
4431 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4432 } catch (IOException e) {
4433 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4434 return null;
4435 }
4436 try {
4437 FileUtils.setPermissions(
4438 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4439 -1, -1);
4440 } catch (IOException e) {
4441 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4442 return null;
4443 }
4444 return tmpPackageFile;
4445 }
4446
4447 public void deletePackage(final String packageName,
4448 final IPackageDeleteObserver observer,
4449 final int flags) {
4450 mContext.enforceCallingOrSelfPermission(
4451 android.Manifest.permission.DELETE_PACKAGES, null);
4452 // Queue up an async operation since the package deletion may take a little while.
4453 mHandler.post(new Runnable() {
4454 public void run() {
4455 mHandler.removeCallbacks(this);
4456 final boolean succeded = deletePackageX(packageName, true, true, flags);
4457 if (observer != null) {
4458 try {
4459 observer.packageDeleted(succeded);
4460 } catch (RemoteException e) {
4461 Log.i(TAG, "Observer no longer exists.");
4462 } //end catch
4463 } //end if
4464 } //end run
4465 });
4466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004468 /**
4469 * This method is an internal method that could be get invoked either
4470 * to delete an installed package or to clean up a failed installation.
4471 * After deleting an installed package, a broadcast is sent to notify any
4472 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004473 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 * installation wouldn't have sent the initial broadcast either
4475 * The key steps in deleting a package are
4476 * deleting the package information in internal structures like mPackages,
4477 * deleting the packages base directories through installd
4478 * updating mSettings to reflect current status
4479 * persisting settings for later use
4480 * sending a broadcast if necessary
4481 */
4482
4483 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4484 boolean deleteCodeAndResources, int flags) {
4485 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004486 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487
4488 synchronized (mInstallLock) {
4489 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4490 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004492 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004493 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4494 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4495
4496 // If the removed package was a system update, the old system packaged
4497 // was re-enabled; we need to broadcast this information
4498 if (systemUpdate) {
4499 Bundle extras = new Bundle(1);
4500 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4501 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4502
4503 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4504 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004506 }
4507 return res;
4508 }
4509
4510 static class PackageRemovedInfo {
4511 String removedPackage;
4512 int uid = -1;
4513 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004514 boolean isRemovedPackageSystemUpdate = false;
4515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 void sendBroadcast(boolean fullRemove, boolean replacing) {
4517 Bundle extras = new Bundle(1);
4518 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4519 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4520 if (replacing) {
4521 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4522 }
4523 if (removedPackage != null) {
4524 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4525 }
4526 if (removedUid >= 0) {
4527 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4528 }
4529 }
4530 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 /*
4533 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4534 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004535 * 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 -08004536 * delete a partially installed application.
4537 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004538 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004539 int flags) {
4540 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004541 if (outInfo != null) {
4542 outInfo.removedPackage = packageName;
4543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004544 removePackageLI(p, true);
4545 // Retrieve object to delete permissions for shared user later on
4546 PackageSetting deletedPs;
4547 synchronized (mPackages) {
4548 deletedPs = mSettings.mPackages.get(packageName);
4549 }
4550 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004551 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004553 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 if (retCode < 0) {
4555 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4556 + packageName + ", retcode=" + retCode);
4557 // we don't consider this to be a failure of the core package deletion
4558 }
4559 } else {
4560 //for emulator
4561 PackageParser.Package pkg = mPackages.get(packageName);
4562 File dataDir = new File(pkg.applicationInfo.dataDir);
4563 dataDir.delete();
4564 }
4565 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004566 if (outInfo != null) {
4567 outInfo.removedUid = mSettings.removePackageLP(packageName);
4568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 }
4570 }
4571 synchronized (mPackages) {
4572 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4573 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004574 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576 // Save settings now
4577 mSettings.writeLP ();
4578 }
4579 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 /*
4582 * Tries to delete system package.
4583 */
4584 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004585 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 ApplicationInfo applicationInfo = p.applicationInfo;
4587 //applicable for non-partially installed applications only
4588 if (applicationInfo == null) {
4589 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4590 return false;
4591 }
4592 PackageSetting ps = null;
4593 // Confirm if the system package has been updated
4594 // An updated system app can be deleted. This will also have to restore
4595 // the system pkg from system partition
4596 synchronized (mPackages) {
4597 ps = mSettings.getDisabledSystemPkg(p.packageName);
4598 }
4599 if (ps == null) {
4600 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4601 return false;
4602 } else {
4603 Log.i(TAG, "Deleting system pkg from data partition");
4604 }
4605 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004606 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004607 boolean deleteCodeAndResources = false;
4608 if (ps.versionCode < p.mVersionCode) {
4609 // Delete code and resources for downgrades
4610 deleteCodeAndResources = true;
4611 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4612 flags &= ~PackageManager.DONT_DELETE_DATA;
4613 }
4614 } else {
4615 // Preserve data by setting flag
4616 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4617 flags |= PackageManager.DONT_DELETE_DATA;
4618 }
4619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4621 if (!ret) {
4622 return false;
4623 }
4624 synchronized (mPackages) {
4625 // Reinstate the old system package
4626 mSettings.enableSystemPackageLP(p.packageName);
4627 }
4628 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004629 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004631 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 if (newPkg == null) {
4634 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4635 return false;
4636 }
4637 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004638 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004639 mSettings.writeLP();
4640 }
4641 return true;
4642 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004643
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004644 private void deletePackageResourcesLI(String packageName,
4645 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004646 if (sourceDir != null) {
4647 File sourceFile = new File(sourceDir);
4648 if (!sourceFile.exists()) {
4649 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4650 }
4651 // Delete application's code and resources
4652 sourceFile.delete();
4653 if (mInstaller != null) {
4654 int retCode = mInstaller.rmdex(sourceFile.toString());
4655 if (retCode < 0) {
4656 Log.w(TAG, "Couldn't remove dex file for package: "
4657 + packageName + " at location "
4658 + sourceFile.toString() + ", retcode=" + retCode);
4659 // we don't consider this to be a failure of the core package deletion
4660 }
4661 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004662 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004663 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4664 final File publicSourceFile = new File(publicSourceDir);
4665 if (!publicSourceFile.exists()) {
4666 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4667 }
4668 if (publicSourceFile.exists()) {
4669 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004670 }
4671 }
4672 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4675 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4676 ApplicationInfo applicationInfo = p.applicationInfo;
4677 if (applicationInfo == null) {
4678 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4679 return false;
4680 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004681 if (outInfo != null) {
4682 outInfo.uid = applicationInfo.uid;
4683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004684
4685 // Delete package data from internal structures and also remove data if flag is set
4686 removePackageDataLI(p, outInfo, flags);
4687
4688 // Delete application code and resources
4689 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004690 deletePackageResourcesLI(applicationInfo.packageName,
4691 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 }
4693 return true;
4694 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 /*
4697 * This method handles package deletion in general
4698 */
4699 private boolean deletePackageLI(String packageName,
4700 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4701 if (packageName == null) {
4702 Log.w(TAG, "Attempt to delete null packageName.");
4703 return false;
4704 }
4705 PackageParser.Package p;
4706 boolean dataOnly = false;
4707 synchronized (mPackages) {
4708 p = mPackages.get(packageName);
4709 if (p == null) {
4710 //this retrieves partially installed apps
4711 dataOnly = true;
4712 PackageSetting ps = mSettings.mPackages.get(packageName);
4713 if (ps == null) {
4714 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4715 return false;
4716 }
4717 p = ps.pkg;
4718 }
4719 }
4720 if (p == null) {
4721 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4722 return false;
4723 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004725 if (dataOnly) {
4726 // Delete application data first
4727 removePackageDataLI(p, outInfo, flags);
4728 return true;
4729 }
4730 // At this point the package should have ApplicationInfo associated with it
4731 if (p.applicationInfo == null) {
4732 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4733 return false;
4734 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004735 boolean onSd = (p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0;
4736 // Mount sd container if needed
4737 if (onSd) {
4738 // TODO Better error handling from MountService api later
4739 mountSdDir(p.packageName, Process.SYSTEM_UID) ;
4740 }
4741 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4743 Log.i(TAG, "Removing system package:"+p.packageName);
4744 // When an updated system application is deleted we delete the existing resources as well and
4745 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004746 ret = deleteSystemPackageLI(p, flags, outInfo);
4747 } else {
4748 Log.i(TAG, "Removing non-system package:"+p.packageName);
4749 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004751 if (ret && onSd) {
4752 // Post a delayed destroy on the container since there might
4753 // be active processes holding open file handles to package
4754 // resources which will get killed by the process killer when
4755 // destroying the container. This might even kill the current
4756 // process and crash the system. Delay the destroy a bit so
4757 // that the active processes get to handle the uninstall broadcasts.
4758 sendDelayedDestroySdDir(packageName);
4759 }
4760 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004763 public void clearApplicationUserData(final String packageName,
4764 final IPackageDataObserver observer) {
4765 mContext.enforceCallingOrSelfPermission(
4766 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4767 // Queue up an async operation since the package deletion may take a little while.
4768 mHandler.post(new Runnable() {
4769 public void run() {
4770 mHandler.removeCallbacks(this);
4771 final boolean succeeded;
4772 synchronized (mInstallLock) {
4773 succeeded = clearApplicationUserDataLI(packageName);
4774 }
4775 if (succeeded) {
4776 // invoke DeviceStorageMonitor's update method to clear any notifications
4777 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4778 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4779 if (dsm != null) {
4780 dsm.updateMemory();
4781 }
4782 }
4783 if(observer != null) {
4784 try {
4785 observer.onRemoveCompleted(packageName, succeeded);
4786 } catch (RemoteException e) {
4787 Log.i(TAG, "Observer no longer exists.");
4788 }
4789 } //end if observer
4790 } //end run
4791 });
4792 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004794 private boolean clearApplicationUserDataLI(String packageName) {
4795 if (packageName == null) {
4796 Log.w(TAG, "Attempt to delete null packageName.");
4797 return false;
4798 }
4799 PackageParser.Package p;
4800 boolean dataOnly = false;
4801 synchronized (mPackages) {
4802 p = mPackages.get(packageName);
4803 if(p == null) {
4804 dataOnly = true;
4805 PackageSetting ps = mSettings.mPackages.get(packageName);
4806 if((ps == null) || (ps.pkg == null)) {
4807 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4808 return false;
4809 }
4810 p = ps.pkg;
4811 }
4812 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004813 boolean useEncryptedFSDir = false;
4814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 if(!dataOnly) {
4816 //need to check this only for fully installed applications
4817 if (p == null) {
4818 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4819 return false;
4820 }
4821 final ApplicationInfo applicationInfo = p.applicationInfo;
4822 if (applicationInfo == null) {
4823 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4824 return false;
4825 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004826 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 }
4828 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004829 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830 if (retCode < 0) {
4831 Log.w(TAG, "Couldn't remove cache files for package: "
4832 + packageName);
4833 return false;
4834 }
4835 }
4836 return true;
4837 }
4838
4839 public void deleteApplicationCacheFiles(final String packageName,
4840 final IPackageDataObserver observer) {
4841 mContext.enforceCallingOrSelfPermission(
4842 android.Manifest.permission.DELETE_CACHE_FILES, null);
4843 // Queue up an async operation since the package deletion may take a little while.
4844 mHandler.post(new Runnable() {
4845 public void run() {
4846 mHandler.removeCallbacks(this);
4847 final boolean succeded;
4848 synchronized (mInstallLock) {
4849 succeded = deleteApplicationCacheFilesLI(packageName);
4850 }
4851 if(observer != null) {
4852 try {
4853 observer.onRemoveCompleted(packageName, succeded);
4854 } catch (RemoteException e) {
4855 Log.i(TAG, "Observer no longer exists.");
4856 }
4857 } //end if observer
4858 } //end run
4859 });
4860 }
4861
4862 private boolean deleteApplicationCacheFilesLI(String packageName) {
4863 if (packageName == null) {
4864 Log.w(TAG, "Attempt to delete null packageName.");
4865 return false;
4866 }
4867 PackageParser.Package p;
4868 synchronized (mPackages) {
4869 p = mPackages.get(packageName);
4870 }
4871 if (p == null) {
4872 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4873 return false;
4874 }
4875 final ApplicationInfo applicationInfo = p.applicationInfo;
4876 if (applicationInfo == null) {
4877 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4878 return false;
4879 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004880 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004882 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 if (retCode < 0) {
4884 Log.w(TAG, "Couldn't remove cache files for package: "
4885 + packageName);
4886 return false;
4887 }
4888 }
4889 return true;
4890 }
4891
4892 public void getPackageSizeInfo(final String packageName,
4893 final IPackageStatsObserver observer) {
4894 mContext.enforceCallingOrSelfPermission(
4895 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4896 // Queue up an async operation since the package deletion may take a little while.
4897 mHandler.post(new Runnable() {
4898 public void run() {
4899 mHandler.removeCallbacks(this);
4900 PackageStats lStats = new PackageStats(packageName);
4901 final boolean succeded;
4902 synchronized (mInstallLock) {
4903 succeded = getPackageSizeInfoLI(packageName, lStats);
4904 }
4905 if(observer != null) {
4906 try {
4907 observer.onGetStatsCompleted(lStats, succeded);
4908 } catch (RemoteException e) {
4909 Log.i(TAG, "Observer no longer exists.");
4910 }
4911 } //end if observer
4912 } //end run
4913 });
4914 }
4915
4916 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4917 if (packageName == null) {
4918 Log.w(TAG, "Attempt to get size of null packageName.");
4919 return false;
4920 }
4921 PackageParser.Package p;
4922 boolean dataOnly = false;
4923 synchronized (mPackages) {
4924 p = mPackages.get(packageName);
4925 if(p == null) {
4926 dataOnly = true;
4927 PackageSetting ps = mSettings.mPackages.get(packageName);
4928 if((ps == null) || (ps.pkg == null)) {
4929 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4930 return false;
4931 }
4932 p = ps.pkg;
4933 }
4934 }
4935 String publicSrcDir = null;
4936 if(!dataOnly) {
4937 final ApplicationInfo applicationInfo = p.applicationInfo;
4938 if (applicationInfo == null) {
4939 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4940 return false;
4941 }
4942 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4943 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004944 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 if (mInstaller != null) {
4946 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08004947 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004948 if (res < 0) {
4949 return false;
4950 } else {
4951 return true;
4952 }
4953 }
4954 return true;
4955 }
4956
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958 public void addPackageToPreferred(String packageName) {
4959 mContext.enforceCallingOrSelfPermission(
4960 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004961 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004962 }
4963
4964 public void removePackageFromPreferred(String packageName) {
4965 mContext.enforceCallingOrSelfPermission(
4966 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004967 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004968 }
4969
4970 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004971 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004972 }
4973
4974 public void addPreferredActivity(IntentFilter filter, int match,
4975 ComponentName[] set, ComponentName activity) {
4976 mContext.enforceCallingOrSelfPermission(
4977 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4978
4979 synchronized (mPackages) {
4980 Log.i(TAG, "Adding preferred activity " + activity + ":");
4981 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4982 mSettings.mPreferredActivities.addFilter(
4983 new PreferredActivity(filter, match, set, activity));
4984 mSettings.writeLP();
4985 }
4986 }
4987
Satish Sampath8dbe6122009-06-02 23:35:54 +01004988 public void replacePreferredActivity(IntentFilter filter, int match,
4989 ComponentName[] set, ComponentName activity) {
4990 mContext.enforceCallingOrSelfPermission(
4991 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4992 if (filter.countActions() != 1) {
4993 throw new IllegalArgumentException(
4994 "replacePreferredActivity expects filter to have only 1 action.");
4995 }
4996 if (filter.countCategories() != 1) {
4997 throw new IllegalArgumentException(
4998 "replacePreferredActivity expects filter to have only 1 category.");
4999 }
5000 if (filter.countDataAuthorities() != 0
5001 || filter.countDataPaths() != 0
5002 || filter.countDataSchemes() != 0
5003 || filter.countDataTypes() != 0) {
5004 throw new IllegalArgumentException(
5005 "replacePreferredActivity expects filter to have no data authorities, " +
5006 "paths, schemes or types.");
5007 }
5008 synchronized (mPackages) {
5009 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5010 String action = filter.getAction(0);
5011 String category = filter.getCategory(0);
5012 while (it.hasNext()) {
5013 PreferredActivity pa = it.next();
5014 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5015 it.remove();
5016 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5017 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5018 }
5019 }
5020 addPreferredActivity(filter, match, set, activity);
5021 }
5022 }
5023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 public void clearPackagePreferredActivities(String packageName) {
5025 mContext.enforceCallingOrSelfPermission(
5026 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5027
5028 synchronized (mPackages) {
5029 if (clearPackagePreferredActivitiesLP(packageName)) {
5030 mSettings.writeLP();
5031 }
5032 }
5033 }
5034
5035 boolean clearPackagePreferredActivitiesLP(String packageName) {
5036 boolean changed = false;
5037 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5038 while (it.hasNext()) {
5039 PreferredActivity pa = it.next();
5040 if (pa.mActivity.getPackageName().equals(packageName)) {
5041 it.remove();
5042 changed = true;
5043 }
5044 }
5045 return changed;
5046 }
5047
5048 public int getPreferredActivities(List<IntentFilter> outFilters,
5049 List<ComponentName> outActivities, String packageName) {
5050
5051 int num = 0;
5052 synchronized (mPackages) {
5053 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5054 while (it.hasNext()) {
5055 PreferredActivity pa = it.next();
5056 if (packageName == null
5057 || pa.mActivity.getPackageName().equals(packageName)) {
5058 if (outFilters != null) {
5059 outFilters.add(new IntentFilter(pa));
5060 }
5061 if (outActivities != null) {
5062 outActivities.add(pa.mActivity);
5063 }
5064 }
5065 }
5066 }
5067
5068 return num;
5069 }
5070
5071 public void setApplicationEnabledSetting(String appPackageName,
5072 int newState, int flags) {
5073 setEnabledSetting(appPackageName, null, newState, flags);
5074 }
5075
5076 public void setComponentEnabledSetting(ComponentName componentName,
5077 int newState, int flags) {
5078 setEnabledSetting(componentName.getPackageName(),
5079 componentName.getClassName(), newState, flags);
5080 }
5081
5082 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005083 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005084 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5085 || newState == COMPONENT_ENABLED_STATE_ENABLED
5086 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5087 throw new IllegalArgumentException("Invalid new component state: "
5088 + newState);
5089 }
5090 PackageSetting pkgSetting;
5091 final int uid = Binder.getCallingUid();
5092 final int permission = mContext.checkCallingPermission(
5093 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5094 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005095 boolean sendNow = false;
5096 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005097 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005099 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005101 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005103 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005105 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 }
5107 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005108 "Unknown component: " + packageName
5109 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 }
5111 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5112 throw new SecurityException(
5113 "Permission Denial: attempt to change component state from pid="
5114 + Binder.getCallingPid()
5115 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5116 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005117 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 // We're dealing with an application/package level state change
5119 pkgSetting.enabled = newState;
5120 } else {
5121 // We're dealing with a component level state change
5122 switch (newState) {
5123 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005124 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005125 break;
5126 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005127 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 break;
5129 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005130 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 break;
5132 default:
5133 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005134 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005135 }
5136 }
5137 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005138 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005139 components = mPendingBroadcasts.get(packageName);
5140 boolean newPackage = components == null;
5141 if (newPackage) {
5142 components = new ArrayList<String>();
5143 }
5144 if (!components.contains(componentName)) {
5145 components.add(componentName);
5146 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005147 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5148 sendNow = true;
5149 // Purge entry from pending broadcast list if another one exists already
5150 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005151 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005152 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005153 if (newPackage) {
5154 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005155 }
5156 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5157 // Schedule a message
5158 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5159 }
5160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 long callingId = Binder.clearCallingIdentity();
5164 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005165 if (sendNow) {
5166 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005167 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005168 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169 } finally {
5170 Binder.restoreCallingIdentity(callingId);
5171 }
5172 }
5173
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005174 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005175 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5176 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5177 + " components=" + componentNames);
5178 Bundle extras = new Bundle(4);
5179 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5180 String nameList[] = new String[componentNames.size()];
5181 componentNames.toArray(nameList);
5182 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005183 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5184 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005185 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005186 }
5187
Jacek Surazski65e13172009-04-28 15:26:38 +02005188 public String getInstallerPackageName(String packageName) {
5189 synchronized (mPackages) {
5190 PackageSetting pkg = mSettings.mPackages.get(packageName);
5191 if (pkg == null) {
5192 throw new IllegalArgumentException("Unknown package: " + packageName);
5193 }
5194 return pkg.installerPackageName;
5195 }
5196 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005198 public int getApplicationEnabledSetting(String appPackageName) {
5199 synchronized (mPackages) {
5200 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5201 if (pkg == null) {
5202 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5203 }
5204 return pkg.enabled;
5205 }
5206 }
5207
5208 public int getComponentEnabledSetting(ComponentName componentName) {
5209 synchronized (mPackages) {
5210 final String packageNameStr = componentName.getPackageName();
5211 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5212 if (pkg == null) {
5213 throw new IllegalArgumentException("Unknown component: " + componentName);
5214 }
5215 final String classNameStr = componentName.getClassName();
5216 return pkg.currentEnabledStateLP(classNameStr);
5217 }
5218 }
5219
5220 public void enterSafeMode() {
5221 if (!mSystemReady) {
5222 mSafeMode = true;
5223 }
5224 }
5225
5226 public void systemReady() {
5227 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005228
5229 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005230 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005231 mContext.getContentResolver(),
5232 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005233 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005234 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005235 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237 }
5238
5239 public boolean isSafeMode() {
5240 return mSafeMode;
5241 }
5242
5243 public boolean hasSystemUidErrors() {
5244 return mHasSystemUidErrors;
5245 }
5246
5247 static String arrayToString(int[] array) {
5248 StringBuffer buf = new StringBuffer(128);
5249 buf.append('[');
5250 if (array != null) {
5251 for (int i=0; i<array.length; i++) {
5252 if (i > 0) buf.append(", ");
5253 buf.append(array[i]);
5254 }
5255 }
5256 buf.append(']');
5257 return buf.toString();
5258 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 @Override
5261 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5262 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5263 != PackageManager.PERMISSION_GRANTED) {
5264 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5265 + Binder.getCallingPid()
5266 + ", uid=" + Binder.getCallingUid()
5267 + " without permission "
5268 + android.Manifest.permission.DUMP);
5269 return;
5270 }
5271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 synchronized (mPackages) {
5273 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005274 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005275 pw.println(" ");
5276 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005277 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 pw.println(" ");
5279 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005280 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005281 pw.println(" ");
5282 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005283 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 pw.println("Permissions:");
5286 {
5287 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005288 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5289 pw.print(Integer.toHexString(System.identityHashCode(p)));
5290 pw.println("):");
5291 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5292 pw.print(" uid="); pw.print(p.uid);
5293 pw.print(" gids="); pw.print(arrayToString(p.gids));
5294 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 }
5296 }
5297 pw.println(" ");
5298 pw.println("Packages:");
5299 {
5300 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005301 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5302 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5303 pw.println("):");
5304 pw.print(" userId="); pw.print(ps.userId);
5305 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5306 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5307 pw.print(" pkg="); pw.println(ps.pkg);
5308 pw.print(" codePath="); pw.println(ps.codePathString);
5309 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005311 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005312 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005313 pw.print(" supportsScreens=[");
5314 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005315 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005316 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005317 if (!first) pw.print(", ");
5318 first = false;
5319 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005320 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005321 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005322 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005323 if (!first) pw.print(", ");
5324 first = false;
5325 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005326 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005327 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005328 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005329 if (!first) pw.print(", ");
5330 first = false;
5331 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005332 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005333 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005334 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005335 if (!first) pw.print(", ");
5336 first = false;
5337 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005338 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005339 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005340 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5341 if (!first) pw.print(", ");
5342 first = false;
5343 pw.print("anyDensity");
5344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005346 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005347 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5348 pw.print(" signatures="); pw.println(ps.signatures);
5349 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5350 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5351 pw.print(" installStatus="); pw.print(ps.installStatus);
5352 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005353 if (ps.disabledComponents.size() > 0) {
5354 pw.println(" disabledComponents:");
5355 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005356 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 }
5358 }
5359 if (ps.enabledComponents.size() > 0) {
5360 pw.println(" enabledComponents:");
5361 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005362 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005365 if (ps.grantedPermissions.size() > 0) {
5366 pw.println(" grantedPermissions:");
5367 for (String s : ps.grantedPermissions) {
5368 pw.print(" "); pw.println(s);
5369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005371 if (ps.loadedPermissions.size() > 0) {
5372 pw.println(" loadedPermissions:");
5373 for (String s : ps.loadedPermissions) {
5374 pw.print(" "); pw.println(s);
5375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 }
5377 }
5378 }
5379 pw.println(" ");
5380 pw.println("Shared Users:");
5381 {
5382 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005383 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5384 pw.print(Integer.toHexString(System.identityHashCode(su)));
5385 pw.println("):");
5386 pw.print(" userId="); pw.print(su.userId);
5387 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 pw.println(" grantedPermissions:");
5389 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005390 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005391 }
5392 pw.println(" loadedPermissions:");
5393 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005394 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005395 }
5396 }
5397 }
5398 pw.println(" ");
5399 pw.println("Settings parse messages:");
5400 pw.println(mSettings.mReadMessages.toString());
5401 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005402
5403 synchronized (mProviders) {
5404 pw.println(" ");
5405 pw.println("Registered ContentProviders:");
5406 for (PackageParser.Provider p : mProviders.values()) {
5407 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5408 pw.println(p.toString());
5409 }
5410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 }
5412
5413 static final class BasePermission {
5414 final static int TYPE_NORMAL = 0;
5415 final static int TYPE_BUILTIN = 1;
5416 final static int TYPE_DYNAMIC = 2;
5417
5418 final String name;
5419 final String sourcePackage;
5420 final int type;
5421 PackageParser.Permission perm;
5422 PermissionInfo pendingInfo;
5423 int uid;
5424 int[] gids;
5425
5426 BasePermission(String _name, String _sourcePackage, int _type) {
5427 name = _name;
5428 sourcePackage = _sourcePackage;
5429 type = _type;
5430 }
5431 }
5432
5433 static class PackageSignatures {
5434 private Signature[] mSignatures;
5435
5436 PackageSignatures(Signature[] sigs) {
5437 assignSignatures(sigs);
5438 }
5439
5440 PackageSignatures() {
5441 }
5442
5443 void writeXml(XmlSerializer serializer, String tagName,
5444 ArrayList<Signature> pastSignatures) throws IOException {
5445 if (mSignatures == null) {
5446 return;
5447 }
5448 serializer.startTag(null, tagName);
5449 serializer.attribute(null, "count",
5450 Integer.toString(mSignatures.length));
5451 for (int i=0; i<mSignatures.length; i++) {
5452 serializer.startTag(null, "cert");
5453 final Signature sig = mSignatures[i];
5454 final int sigHash = sig.hashCode();
5455 final int numPast = pastSignatures.size();
5456 int j;
5457 for (j=0; j<numPast; j++) {
5458 Signature pastSig = pastSignatures.get(j);
5459 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5460 serializer.attribute(null, "index", Integer.toString(j));
5461 break;
5462 }
5463 }
5464 if (j >= numPast) {
5465 pastSignatures.add(sig);
5466 serializer.attribute(null, "index", Integer.toString(numPast));
5467 serializer.attribute(null, "key", sig.toCharsString());
5468 }
5469 serializer.endTag(null, "cert");
5470 }
5471 serializer.endTag(null, tagName);
5472 }
5473
5474 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5475 throws IOException, XmlPullParserException {
5476 String countStr = parser.getAttributeValue(null, "count");
5477 if (countStr == null) {
5478 reportSettingsProblem(Log.WARN,
5479 "Error in package manager settings: <signatures> has"
5480 + " no count at " + parser.getPositionDescription());
5481 XmlUtils.skipCurrentTag(parser);
5482 }
5483 final int count = Integer.parseInt(countStr);
5484 mSignatures = new Signature[count];
5485 int pos = 0;
5486
5487 int outerDepth = parser.getDepth();
5488 int type;
5489 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5490 && (type != XmlPullParser.END_TAG
5491 || parser.getDepth() > outerDepth)) {
5492 if (type == XmlPullParser.END_TAG
5493 || type == XmlPullParser.TEXT) {
5494 continue;
5495 }
5496
5497 String tagName = parser.getName();
5498 if (tagName.equals("cert")) {
5499 if (pos < count) {
5500 String index = parser.getAttributeValue(null, "index");
5501 if (index != null) {
5502 try {
5503 int idx = Integer.parseInt(index);
5504 String key = parser.getAttributeValue(null, "key");
5505 if (key == null) {
5506 if (idx >= 0 && idx < pastSignatures.size()) {
5507 Signature sig = pastSignatures.get(idx);
5508 if (sig != null) {
5509 mSignatures[pos] = pastSignatures.get(idx);
5510 pos++;
5511 } else {
5512 reportSettingsProblem(Log.WARN,
5513 "Error in package manager settings: <cert> "
5514 + "index " + index + " is not defined at "
5515 + parser.getPositionDescription());
5516 }
5517 } else {
5518 reportSettingsProblem(Log.WARN,
5519 "Error in package manager settings: <cert> "
5520 + "index " + index + " is out of bounds at "
5521 + parser.getPositionDescription());
5522 }
5523 } else {
5524 while (pastSignatures.size() <= idx) {
5525 pastSignatures.add(null);
5526 }
5527 Signature sig = new Signature(key);
5528 pastSignatures.set(idx, sig);
5529 mSignatures[pos] = sig;
5530 pos++;
5531 }
5532 } catch (NumberFormatException e) {
5533 reportSettingsProblem(Log.WARN,
5534 "Error in package manager settings: <cert> "
5535 + "index " + index + " is not a number at "
5536 + parser.getPositionDescription());
5537 }
5538 } else {
5539 reportSettingsProblem(Log.WARN,
5540 "Error in package manager settings: <cert> has"
5541 + " no index at " + parser.getPositionDescription());
5542 }
5543 } else {
5544 reportSettingsProblem(Log.WARN,
5545 "Error in package manager settings: too "
5546 + "many <cert> tags, expected " + count
5547 + " at " + parser.getPositionDescription());
5548 }
5549 } else {
5550 reportSettingsProblem(Log.WARN,
5551 "Unknown element under <cert>: "
5552 + parser.getName());
5553 }
5554 XmlUtils.skipCurrentTag(parser);
5555 }
5556
5557 if (pos < count) {
5558 // Should never happen -- there is an error in the written
5559 // settings -- but if it does we don't want to generate
5560 // a bad array.
5561 Signature[] newSigs = new Signature[pos];
5562 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5563 mSignatures = newSigs;
5564 }
5565 }
5566
5567 /**
5568 * If any of the given 'sigs' is contained in the existing signatures,
5569 * then completely replace the current signatures with the ones in
5570 * 'sigs'. This is used for updating an existing package to a newly
5571 * installed version.
5572 */
5573 boolean updateSignatures(Signature[] sigs, boolean update) {
5574 if (mSignatures == null) {
5575 if (update) {
5576 assignSignatures(sigs);
5577 }
5578 return true;
5579 }
5580 if (sigs == null) {
5581 return false;
5582 }
5583
5584 for (int i=0; i<sigs.length; i++) {
5585 Signature sig = sigs[i];
5586 for (int j=0; j<mSignatures.length; j++) {
5587 if (mSignatures[j].equals(sig)) {
5588 if (update) {
5589 assignSignatures(sigs);
5590 }
5591 return true;
5592 }
5593 }
5594 }
5595 return false;
5596 }
5597
5598 /**
5599 * If any of the given 'sigs' is contained in the existing signatures,
5600 * then add in any new signatures found in 'sigs'. This is used for
5601 * including a new package into an existing shared user id.
5602 */
5603 boolean mergeSignatures(Signature[] sigs, boolean update) {
5604 if (mSignatures == null) {
5605 if (update) {
5606 assignSignatures(sigs);
5607 }
5608 return true;
5609 }
5610 if (sigs == null) {
5611 return false;
5612 }
5613
5614 Signature[] added = null;
5615 int addedCount = 0;
5616 boolean haveMatch = false;
5617 for (int i=0; i<sigs.length; i++) {
5618 Signature sig = sigs[i];
5619 boolean found = false;
5620 for (int j=0; j<mSignatures.length; j++) {
5621 if (mSignatures[j].equals(sig)) {
5622 found = true;
5623 haveMatch = true;
5624 break;
5625 }
5626 }
5627
5628 if (!found) {
5629 if (added == null) {
5630 added = new Signature[sigs.length];
5631 }
5632 added[i] = sig;
5633 addedCount++;
5634 }
5635 }
5636
5637 if (!haveMatch) {
5638 // Nothing matched -- reject the new signatures.
5639 return false;
5640 }
5641 if (added == null) {
5642 // Completely matched -- nothing else to do.
5643 return true;
5644 }
5645
5646 // Add additional signatures in.
5647 if (update) {
5648 Signature[] total = new Signature[addedCount+mSignatures.length];
5649 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5650 int j = mSignatures.length;
5651 for (int i=0; i<added.length; i++) {
5652 if (added[i] != null) {
5653 total[j] = added[i];
5654 j++;
5655 }
5656 }
5657 mSignatures = total;
5658 }
5659 return true;
5660 }
5661
5662 private void assignSignatures(Signature[] sigs) {
5663 if (sigs == null) {
5664 mSignatures = null;
5665 return;
5666 }
5667 mSignatures = new Signature[sigs.length];
5668 for (int i=0; i<sigs.length; i++) {
5669 mSignatures[i] = sigs[i];
5670 }
5671 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005673 @Override
5674 public String toString() {
5675 StringBuffer buf = new StringBuffer(128);
5676 buf.append("PackageSignatures{");
5677 buf.append(Integer.toHexString(System.identityHashCode(this)));
5678 buf.append(" [");
5679 if (mSignatures != null) {
5680 for (int i=0; i<mSignatures.length; i++) {
5681 if (i > 0) buf.append(", ");
5682 buf.append(Integer.toHexString(
5683 System.identityHashCode(mSignatures[i])));
5684 }
5685 }
5686 buf.append("]}");
5687 return buf.toString();
5688 }
5689 }
5690
5691 static class PreferredActivity extends IntentFilter {
5692 final int mMatch;
5693 final String[] mSetPackages;
5694 final String[] mSetClasses;
5695 final String[] mSetComponents;
5696 final ComponentName mActivity;
5697 final String mShortActivity;
5698 String mParseError;
5699
5700 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5701 ComponentName activity) {
5702 super(filter);
5703 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5704 mActivity = activity;
5705 mShortActivity = activity.flattenToShortString();
5706 mParseError = null;
5707 if (set != null) {
5708 final int N = set.length;
5709 String[] myPackages = new String[N];
5710 String[] myClasses = new String[N];
5711 String[] myComponents = new String[N];
5712 for (int i=0; i<N; i++) {
5713 ComponentName cn = set[i];
5714 if (cn == null) {
5715 mSetPackages = null;
5716 mSetClasses = null;
5717 mSetComponents = null;
5718 return;
5719 }
5720 myPackages[i] = cn.getPackageName().intern();
5721 myClasses[i] = cn.getClassName().intern();
5722 myComponents[i] = cn.flattenToShortString().intern();
5723 }
5724 mSetPackages = myPackages;
5725 mSetClasses = myClasses;
5726 mSetComponents = myComponents;
5727 } else {
5728 mSetPackages = null;
5729 mSetClasses = null;
5730 mSetComponents = null;
5731 }
5732 }
5733
5734 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5735 IOException {
5736 mShortActivity = parser.getAttributeValue(null, "name");
5737 mActivity = ComponentName.unflattenFromString(mShortActivity);
5738 if (mActivity == null) {
5739 mParseError = "Bad activity name " + mShortActivity;
5740 }
5741 String matchStr = parser.getAttributeValue(null, "match");
5742 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5743 String setCountStr = parser.getAttributeValue(null, "set");
5744 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5745
5746 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5747 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5748 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5749
5750 int setPos = 0;
5751
5752 int outerDepth = parser.getDepth();
5753 int type;
5754 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5755 && (type != XmlPullParser.END_TAG
5756 || parser.getDepth() > outerDepth)) {
5757 if (type == XmlPullParser.END_TAG
5758 || type == XmlPullParser.TEXT) {
5759 continue;
5760 }
5761
5762 String tagName = parser.getName();
5763 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5764 // + parser.getDepth() + " tag=" + tagName);
5765 if (tagName.equals("set")) {
5766 String name = parser.getAttributeValue(null, "name");
5767 if (name == null) {
5768 if (mParseError == null) {
5769 mParseError = "No name in set tag in preferred activity "
5770 + mShortActivity;
5771 }
5772 } else if (setPos >= setCount) {
5773 if (mParseError == null) {
5774 mParseError = "Too many set tags in preferred activity "
5775 + mShortActivity;
5776 }
5777 } else {
5778 ComponentName cn = ComponentName.unflattenFromString(name);
5779 if (cn == null) {
5780 if (mParseError == null) {
5781 mParseError = "Bad set name " + name + " in preferred activity "
5782 + mShortActivity;
5783 }
5784 } else {
5785 myPackages[setPos] = cn.getPackageName();
5786 myClasses[setPos] = cn.getClassName();
5787 myComponents[setPos] = name;
5788 setPos++;
5789 }
5790 }
5791 XmlUtils.skipCurrentTag(parser);
5792 } else if (tagName.equals("filter")) {
5793 //Log.i(TAG, "Starting to parse filter...");
5794 readFromXml(parser);
5795 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5796 // + parser.getDepth() + " tag=" + parser.getName());
5797 } else {
5798 reportSettingsProblem(Log.WARN,
5799 "Unknown element under <preferred-activities>: "
5800 + parser.getName());
5801 XmlUtils.skipCurrentTag(parser);
5802 }
5803 }
5804
5805 if (setPos != setCount) {
5806 if (mParseError == null) {
5807 mParseError = "Not enough set tags (expected " + setCount
5808 + " but found " + setPos + ") in " + mShortActivity;
5809 }
5810 }
5811
5812 mSetPackages = myPackages;
5813 mSetClasses = myClasses;
5814 mSetComponents = myComponents;
5815 }
5816
5817 public void writeToXml(XmlSerializer serializer) throws IOException {
5818 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5819 serializer.attribute(null, "name", mShortActivity);
5820 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5821 serializer.attribute(null, "set", Integer.toString(NS));
5822 for (int s=0; s<NS; s++) {
5823 serializer.startTag(null, "set");
5824 serializer.attribute(null, "name", mSetComponents[s]);
5825 serializer.endTag(null, "set");
5826 }
5827 serializer.startTag(null, "filter");
5828 super.writeToXml(serializer);
5829 serializer.endTag(null, "filter");
5830 }
5831
5832 boolean sameSet(List<ResolveInfo> query, int priority) {
5833 if (mSetPackages == null) return false;
5834 final int NQ = query.size();
5835 final int NS = mSetPackages.length;
5836 int numMatch = 0;
5837 for (int i=0; i<NQ; i++) {
5838 ResolveInfo ri = query.get(i);
5839 if (ri.priority != priority) continue;
5840 ActivityInfo ai = ri.activityInfo;
5841 boolean good = false;
5842 for (int j=0; j<NS; j++) {
5843 if (mSetPackages[j].equals(ai.packageName)
5844 && mSetClasses[j].equals(ai.name)) {
5845 numMatch++;
5846 good = true;
5847 break;
5848 }
5849 }
5850 if (!good) return false;
5851 }
5852 return numMatch == NS;
5853 }
5854 }
5855
5856 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005857 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005859 HashSet<String> grantedPermissions = new HashSet<String>();
5860 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005864 GrantedPermissions(int pkgFlags) {
5865 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5866 }
5867 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005869 /**
5870 * Settings base class for pending and resolved classes.
5871 */
5872 static class PackageSettingBase extends GrantedPermissions {
5873 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005874 File codePath;
5875 String codePathString;
5876 File resourcePath;
5877 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 private long timeStamp;
5879 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005880 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881
5882 PackageSignatures signatures = new PackageSignatures();
5883
5884 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 /* Explicitly disabled components */
5887 HashSet<String> disabledComponents = new HashSet<String>(0);
5888 /* Explicitly enabled components */
5889 HashSet<String> enabledComponents = new HashSet<String>(0);
5890 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5891 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005892
Jacek Surazski65e13172009-04-28 15:26:38 +02005893 /* package name of the app that installed this package */
5894 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895
5896 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005897 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005898 super(pkgFlags);
5899 this.name = name;
5900 this.codePath = codePath;
5901 this.codePathString = codePath.toString();
5902 this.resourcePath = resourcePath;
5903 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005904 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 }
5906
Jacek Surazski65e13172009-04-28 15:26:38 +02005907 public void setInstallerPackageName(String packageName) {
5908 installerPackageName = packageName;
5909 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005910
Jacek Surazski65e13172009-04-28 15:26:38 +02005911 String getInstallerPackageName() {
5912 return installerPackageName;
5913 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 public void setInstallStatus(int newStatus) {
5916 installStatus = newStatus;
5917 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 public int getInstallStatus() {
5920 return installStatus;
5921 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 public void setTimeStamp(long newStamp) {
5924 if (newStamp != timeStamp) {
5925 timeStamp = newStamp;
5926 timeStampString = Long.toString(newStamp);
5927 }
5928 }
5929
5930 public void setTimeStamp(long newStamp, String newStampStr) {
5931 timeStamp = newStamp;
5932 timeStampString = newStampStr;
5933 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 public long getTimeStamp() {
5936 return timeStamp;
5937 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 public String getTimeStampStr() {
5940 return timeStampString;
5941 }
5942
5943 public void copyFrom(PackageSettingBase base) {
5944 grantedPermissions = base.grantedPermissions;
5945 gids = base.gids;
5946 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 timeStamp = base.timeStamp;
5949 timeStampString = base.timeStampString;
5950 signatures = base.signatures;
5951 permissionsFixed = base.permissionsFixed;
5952 disabledComponents = base.disabledComponents;
5953 enabledComponents = base.enabledComponents;
5954 enabled = base.enabled;
5955 installStatus = base.installStatus;
5956 }
5957
5958 void enableComponentLP(String componentClassName) {
5959 disabledComponents.remove(componentClassName);
5960 enabledComponents.add(componentClassName);
5961 }
5962
5963 void disableComponentLP(String componentClassName) {
5964 enabledComponents.remove(componentClassName);
5965 disabledComponents.add(componentClassName);
5966 }
5967
5968 void restoreComponentLP(String componentClassName) {
5969 enabledComponents.remove(componentClassName);
5970 disabledComponents.remove(componentClassName);
5971 }
5972
5973 int currentEnabledStateLP(String componentName) {
5974 if (enabledComponents.contains(componentName)) {
5975 return COMPONENT_ENABLED_STATE_ENABLED;
5976 } else if (disabledComponents.contains(componentName)) {
5977 return COMPONENT_ENABLED_STATE_DISABLED;
5978 } else {
5979 return COMPONENT_ENABLED_STATE_DEFAULT;
5980 }
5981 }
5982 }
5983
5984 /**
5985 * Settings data for a particular package we know about.
5986 */
5987 static final class PackageSetting extends PackageSettingBase {
5988 int userId;
5989 PackageParser.Package pkg;
5990 SharedUserSetting sharedUser;
5991
5992 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005993 int pVersionCode, int pkgFlags) {
5994 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 @Override
5998 public String toString() {
5999 return "PackageSetting{"
6000 + Integer.toHexString(System.identityHashCode(this))
6001 + " " + name + "/" + userId + "}";
6002 }
6003 }
6004
6005 /**
6006 * Settings data for a particular shared user ID we know about.
6007 */
6008 static final class SharedUserSetting extends GrantedPermissions {
6009 final String name;
6010 int userId;
6011 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6012 final PackageSignatures signatures = new PackageSignatures();
6013
6014 SharedUserSetting(String _name, int _pkgFlags) {
6015 super(_pkgFlags);
6016 name = _name;
6017 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 @Override
6020 public String toString() {
6021 return "SharedUserSetting{"
6022 + Integer.toHexString(System.identityHashCode(this))
6023 + " " + name + "/" + userId + "}";
6024 }
6025 }
6026
6027 /**
6028 * Holds information about dynamic settings.
6029 */
6030 private static final class Settings {
6031 private final File mSettingsFilename;
6032 private final File mBackupSettingsFilename;
6033 private final HashMap<String, PackageSetting> mPackages =
6034 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 // List of replaced system applications
6036 final HashMap<String, PackageSetting> mDisabledSysPackages =
6037 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006039 // The user's preferred activities associated with particular intent
6040 // filters.
6041 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6042 new IntentResolver<PreferredActivity, PreferredActivity>() {
6043 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006044 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006045 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006046 out.print(prefix); out.print(
6047 Integer.toHexString(System.identityHashCode(filter)));
6048 out.print(' ');
6049 out.print(filter.mActivity.flattenToShortString());
6050 out.print(" match=0x");
6051 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006053 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006055 out.print(prefix); out.print(" ");
6056 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006057 }
6058 }
6059 }
6060 };
6061 private final HashMap<String, SharedUserSetting> mSharedUsers =
6062 new HashMap<String, SharedUserSetting>();
6063 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6064 private final SparseArray<Object> mOtherUserIds =
6065 new SparseArray<Object>();
6066
6067 // For reading/writing settings file.
6068 private final ArrayList<Signature> mPastSignatures =
6069 new ArrayList<Signature>();
6070
6071 // Mapping from permission names to info about them.
6072 final HashMap<String, BasePermission> mPermissions =
6073 new HashMap<String, BasePermission>();
6074
6075 // Mapping from permission tree names to info about them.
6076 final HashMap<String, BasePermission> mPermissionTrees =
6077 new HashMap<String, BasePermission>();
6078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 private final StringBuilder mReadMessages = new StringBuilder();
6080
6081 private static final class PendingPackage extends PackageSettingBase {
6082 final int sharedId;
6083
6084 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006085 int sharedId, int pVersionCode, int pkgFlags) {
6086 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 this.sharedId = sharedId;
6088 }
6089 }
6090 private final ArrayList<PendingPackage> mPendingPackages
6091 = new ArrayList<PendingPackage>();
6092
6093 Settings() {
6094 File dataDir = Environment.getDataDirectory();
6095 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006096 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6097 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006098 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006099 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006100 FileUtils.setPermissions(systemDir.toString(),
6101 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6102 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6103 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006104 FileUtils.setPermissions(systemSecureDir.toString(),
6105 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6106 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6107 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 mSettingsFilename = new File(systemDir, "packages.xml");
6109 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6110 }
6111
6112 PackageSetting getPackageLP(PackageParser.Package pkg,
6113 SharedUserSetting sharedUser, File codePath, File resourcePath,
6114 int pkgFlags, boolean create, boolean add) {
6115 final String name = pkg.packageName;
6116 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006117 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 return p;
6119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006120
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006121 PackageSetting peekPackageLP(String name) {
6122 return mPackages.get(name);
6123 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 PackageSetting p = mPackages.get(name);
6125 if (p != null && p.codePath.getPath().equals(codePath)) {
6126 return p;
6127 }
6128 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006129 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006130 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 void setInstallStatus(String pkgName, int status) {
6133 PackageSetting p = mPackages.get(pkgName);
6134 if(p != null) {
6135 if(p.getInstallStatus() != status) {
6136 p.setInstallStatus(status);
6137 }
6138 }
6139 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006140
Jacek Surazski65e13172009-04-28 15:26:38 +02006141 void setInstallerPackageName(String pkgName,
6142 String installerPkgName) {
6143 PackageSetting p = mPackages.get(pkgName);
6144 if(p != null) {
6145 p.setInstallerPackageName(installerPkgName);
6146 }
6147 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006148
Jacek Surazski65e13172009-04-28 15:26:38 +02006149 String getInstallerPackageName(String pkgName) {
6150 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006151 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006152 }
6153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006154 int getInstallStatus(String pkgName) {
6155 PackageSetting p = mPackages.get(pkgName);
6156 if(p != null) {
6157 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006159 return -1;
6160 }
6161
6162 SharedUserSetting getSharedUserLP(String name,
6163 int pkgFlags, boolean create) {
6164 SharedUserSetting s = mSharedUsers.get(name);
6165 if (s == null) {
6166 if (!create) {
6167 return null;
6168 }
6169 s = new SharedUserSetting(name, pkgFlags);
6170 if (MULTIPLE_APPLICATION_UIDS) {
6171 s.userId = newUserIdLP(s);
6172 } else {
6173 s.userId = FIRST_APPLICATION_UID;
6174 }
6175 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6176 // < 0 means we couldn't assign a userid; fall out and return
6177 // s, which is currently null
6178 if (s.userId >= 0) {
6179 mSharedUsers.put(name, s);
6180 }
6181 }
6182
6183 return s;
6184 }
6185
6186 int disableSystemPackageLP(String name) {
6187 PackageSetting p = mPackages.get(name);
6188 if(p == null) {
6189 Log.w(TAG, "Package:"+name+" is not an installed package");
6190 return -1;
6191 }
6192 PackageSetting dp = mDisabledSysPackages.get(name);
6193 // always make sure the system package code and resource paths dont change
6194 if(dp == null) {
6195 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6196 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6197 }
6198 mDisabledSysPackages.put(name, p);
6199 }
6200 return removePackageLP(name);
6201 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 PackageSetting enableSystemPackageLP(String name) {
6204 PackageSetting p = mDisabledSysPackages.get(name);
6205 if(p == null) {
6206 Log.w(TAG, "Package:"+name+" is not disabled");
6207 return null;
6208 }
6209 // Reset flag in ApplicationInfo object
6210 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6211 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6212 }
6213 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006214 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 mDisabledSysPackages.remove(name);
6216 return ret;
6217 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006220 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 PackageSetting p = mPackages.get(name);
6222 if (p != null) {
6223 if (p.userId == uid) {
6224 return p;
6225 }
6226 reportSettingsProblem(Log.ERROR,
6227 "Adding duplicate package, keeping first: " + name);
6228 return null;
6229 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006230 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006231 p.userId = uid;
6232 if (addUserIdLP(uid, p, name)) {
6233 mPackages.put(name, p);
6234 return p;
6235 }
6236 return null;
6237 }
6238
6239 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6240 SharedUserSetting s = mSharedUsers.get(name);
6241 if (s != null) {
6242 if (s.userId == uid) {
6243 return s;
6244 }
6245 reportSettingsProblem(Log.ERROR,
6246 "Adding duplicate shared user, keeping first: " + name);
6247 return null;
6248 }
6249 s = new SharedUserSetting(name, pkgFlags);
6250 s.userId = uid;
6251 if (addUserIdLP(uid, s, name)) {
6252 mSharedUsers.put(name, s);
6253 return s;
6254 }
6255 return null;
6256 }
6257
6258 private PackageSetting getPackageLP(String name,
6259 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006260 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006261 PackageSetting p = mPackages.get(name);
6262 if (p != null) {
6263 if (!p.codePath.equals(codePath)) {
6264 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006265 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006266 // This is an updated system app with versions in both system
6267 // and data partition. Just let the most recent version
6268 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006269 Log.w(TAG, "Trying to update system app code path from " +
6270 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006271 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006272 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006273 reportSettingsProblem(Log.WARN,
6274 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006275 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006277 }
6278 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 reportSettingsProblem(Log.WARN,
6280 "Package " + name + " shared user changed from "
6281 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6282 + " to "
6283 + (sharedUser != null ? sharedUser.name : "<nothing>")
6284 + "; replacing with new");
6285 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006286 } else {
6287 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6288 // If what we are scanning is a system package, then
6289 // make it so, regardless of whether it was previously
6290 // installed only in the data partition.
6291 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 }
6294 }
6295 if (p == null) {
6296 // Create a new PackageSettings entry. this can end up here because
6297 // of code path mismatch or user id mismatch of an updated system partition
6298 if (!create) {
6299 return null;
6300 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006301 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006303 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 if (sharedUser != null) {
6305 p.userId = sharedUser.userId;
6306 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006307 // Clone the setting here for disabled system packages
6308 PackageSetting dis = mDisabledSysPackages.get(name);
6309 if (dis != null) {
6310 // For disabled packages a new setting is created
6311 // from the existing user id. This still has to be
6312 // added to list of user id's
6313 // Copy signatures from previous setting
6314 if (dis.signatures.mSignatures != null) {
6315 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6316 }
6317 p.userId = dis.userId;
6318 // Clone permissions
6319 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6320 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6321 // Clone component info
6322 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6323 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6324 // Add new setting to list of user ids
6325 addUserIdLP(p.userId, p, name);
6326 } else {
6327 // Assign new user id
6328 p.userId = newUserIdLP(p);
6329 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 } else {
6331 p.userId = FIRST_APPLICATION_UID;
6332 }
6333 if (p.userId < 0) {
6334 reportSettingsProblem(Log.WARN,
6335 "Package " + name + " could not be assigned a valid uid");
6336 return null;
6337 }
6338 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006339 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006340 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006341 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 }
6343 }
6344 return p;
6345 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006346
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006347 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006348 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006349 String codePath = pkg.applicationInfo.sourceDir;
6350 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006351 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006352 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006353 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006354 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006355 p.codePath = new File(codePath);
6356 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006357 }
6358 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006359 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006360 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006361 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006362 p.resourcePath = new File(resourcePath);
6363 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006364 }
6365 // Update version code if needed
6366 if (pkg.mVersionCode != p.versionCode) {
6367 p.versionCode = pkg.mVersionCode;
6368 }
6369 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6370 }
6371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 // Utility method that adds a PackageSetting to mPackages and
6373 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006374 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 SharedUserSetting sharedUser) {
6376 mPackages.put(name, p);
6377 if (sharedUser != null) {
6378 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6379 reportSettingsProblem(Log.ERROR,
6380 "Package " + p.name + " was user "
6381 + p.sharedUser + " but is now " + sharedUser
6382 + "; I am not changing its files so it will probably fail!");
6383 p.sharedUser.packages.remove(p);
6384 } else if (p.userId != sharedUser.userId) {
6385 reportSettingsProblem(Log.ERROR,
6386 "Package " + p.name + " was user id " + p.userId
6387 + " but is now user " + sharedUser
6388 + " with id " + sharedUser.userId
6389 + "; I am not changing its files so it will probably fail!");
6390 }
6391
6392 sharedUser.packages.add(p);
6393 p.sharedUser = sharedUser;
6394 p.userId = sharedUser.userId;
6395 }
6396 }
6397
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006398 /*
6399 * Update the shared user setting when a package using
6400 * specifying the shared user id is removed. The gids
6401 * associated with each permission of the deleted package
6402 * are removed from the shared user's gid list only if its
6403 * not in use by other permissions of packages in the
6404 * shared user setting.
6405 */
6406 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6408 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6409 return;
6410 }
6411 // No sharedUserId
6412 if (deletedPs.sharedUser == null) {
6413 return;
6414 }
6415 SharedUserSetting sus = deletedPs.sharedUser;
6416 // Update permissions
6417 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6418 boolean used = false;
6419 if (!sus.grantedPermissions.contains (eachPerm)) {
6420 continue;
6421 }
6422 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006423 if (pkg.pkg != null &&
6424 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6425 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006426 used = true;
6427 break;
6428 }
6429 }
6430 if (!used) {
6431 // can safely delete this permission from list
6432 sus.grantedPermissions.remove(eachPerm);
6433 sus.loadedPermissions.remove(eachPerm);
6434 }
6435 }
6436 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006437 int newGids[] = globalGids;
6438 for (String eachPerm : sus.grantedPermissions) {
6439 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006440 if (bp != null) {
6441 newGids = appendInts(newGids, bp.gids);
6442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 }
6444 sus.gids = newGids;
6445 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 private int removePackageLP(String name) {
6448 PackageSetting p = mPackages.get(name);
6449 if (p != null) {
6450 mPackages.remove(name);
6451 if (p.sharedUser != null) {
6452 p.sharedUser.packages.remove(p);
6453 if (p.sharedUser.packages.size() == 0) {
6454 mSharedUsers.remove(p.sharedUser.name);
6455 removeUserIdLP(p.sharedUser.userId);
6456 return p.sharedUser.userId;
6457 }
6458 } else {
6459 removeUserIdLP(p.userId);
6460 return p.userId;
6461 }
6462 }
6463 return -1;
6464 }
6465
6466 private boolean addUserIdLP(int uid, Object obj, Object name) {
6467 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6468 return false;
6469 }
6470
6471 if (uid >= FIRST_APPLICATION_UID) {
6472 int N = mUserIds.size();
6473 final int index = uid - FIRST_APPLICATION_UID;
6474 while (index >= N) {
6475 mUserIds.add(null);
6476 N++;
6477 }
6478 if (mUserIds.get(index) != null) {
6479 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006480 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 + " name=" + name);
6482 return false;
6483 }
6484 mUserIds.set(index, obj);
6485 } else {
6486 if (mOtherUserIds.get(uid) != null) {
6487 reportSettingsProblem(Log.ERROR,
6488 "Adding duplicate shared id: " + uid
6489 + " name=" + name);
6490 return false;
6491 }
6492 mOtherUserIds.put(uid, obj);
6493 }
6494 return true;
6495 }
6496
6497 public Object getUserIdLP(int uid) {
6498 if (uid >= FIRST_APPLICATION_UID) {
6499 int N = mUserIds.size();
6500 final int index = uid - FIRST_APPLICATION_UID;
6501 return index < N ? mUserIds.get(index) : null;
6502 } else {
6503 return mOtherUserIds.get(uid);
6504 }
6505 }
6506
6507 private void removeUserIdLP(int uid) {
6508 if (uid >= FIRST_APPLICATION_UID) {
6509 int N = mUserIds.size();
6510 final int index = uid - FIRST_APPLICATION_UID;
6511 if (index < N) mUserIds.set(index, null);
6512 } else {
6513 mOtherUserIds.remove(uid);
6514 }
6515 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 void writeLP() {
6518 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6519
6520 // Keep the old settings around until we know the new ones have
6521 // been successfully written.
6522 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006523 // Presence of backup settings file indicates that we failed
6524 // to persist settings earlier. So preserve the older
6525 // backup for future reference since the current settings
6526 // might have been corrupted.
6527 if (!mBackupSettingsFilename.exists()) {
6528 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6529 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6530 return;
6531 }
6532 } else {
6533 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006535 }
6536
6537 mPastSignatures.clear();
6538
6539 try {
6540 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6541
6542 //XmlSerializer serializer = XmlUtils.serializerInstance();
6543 XmlSerializer serializer = new FastXmlSerializer();
6544 serializer.setOutput(str, "utf-8");
6545 serializer.startDocument(null, true);
6546 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6547
6548 serializer.startTag(null, "packages");
6549
6550 serializer.startTag(null, "permission-trees");
6551 for (BasePermission bp : mPermissionTrees.values()) {
6552 writePermission(serializer, bp);
6553 }
6554 serializer.endTag(null, "permission-trees");
6555
6556 serializer.startTag(null, "permissions");
6557 for (BasePermission bp : mPermissions.values()) {
6558 writePermission(serializer, bp);
6559 }
6560 serializer.endTag(null, "permissions");
6561
6562 for (PackageSetting pkg : mPackages.values()) {
6563 writePackage(serializer, pkg);
6564 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6567 writeDisabledSysPackage(serializer, pkg);
6568 }
6569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006570 serializer.startTag(null, "preferred-activities");
6571 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6572 serializer.startTag(null, "item");
6573 pa.writeToXml(serializer);
6574 serializer.endTag(null, "item");
6575 }
6576 serializer.endTag(null, "preferred-activities");
6577
6578 for (SharedUserSetting usr : mSharedUsers.values()) {
6579 serializer.startTag(null, "shared-user");
6580 serializer.attribute(null, "name", usr.name);
6581 serializer.attribute(null, "userId",
6582 Integer.toString(usr.userId));
6583 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6584 serializer.startTag(null, "perms");
6585 for (String name : usr.grantedPermissions) {
6586 serializer.startTag(null, "item");
6587 serializer.attribute(null, "name", name);
6588 serializer.endTag(null, "item");
6589 }
6590 serializer.endTag(null, "perms");
6591 serializer.endTag(null, "shared-user");
6592 }
6593
6594 serializer.endTag(null, "packages");
6595
6596 serializer.endDocument();
6597
6598 str.flush();
6599 str.close();
6600
6601 // New settings successfully written, old ones are no longer
6602 // needed.
6603 mBackupSettingsFilename.delete();
6604 FileUtils.setPermissions(mSettingsFilename.toString(),
6605 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6606 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6607 |FileUtils.S_IROTH,
6608 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006609 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610
6611 } catch(XmlPullParserException e) {
6612 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 -08006613 } catch(java.io.IOException e) {
6614 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 -08006615 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006616 // Clean up partially written file
6617 if (mSettingsFilename.exists()) {
6618 if (!mSettingsFilename.delete()) {
6619 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6620 }
6621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622 //Debug.stopMethodTracing();
6623 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006624
6625 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006626 throws java.io.IOException {
6627 serializer.startTag(null, "updated-package");
6628 serializer.attribute(null, "name", pkg.name);
6629 serializer.attribute(null, "codePath", pkg.codePathString);
6630 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006631 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006632 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6633 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6634 }
6635 if (pkg.sharedUser == null) {
6636 serializer.attribute(null, "userId",
6637 Integer.toString(pkg.userId));
6638 } else {
6639 serializer.attribute(null, "sharedUserId",
6640 Integer.toString(pkg.userId));
6641 }
6642 serializer.startTag(null, "perms");
6643 if (pkg.sharedUser == null) {
6644 // If this is a shared user, the permissions will
6645 // be written there. We still need to write an
6646 // empty permissions list so permissionsFixed will
6647 // be set.
6648 for (final String name : pkg.grantedPermissions) {
6649 BasePermission bp = mPermissions.get(name);
6650 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6651 // We only need to write signature or system permissions but this wont
6652 // match the semantics of grantedPermissions. So write all permissions.
6653 serializer.startTag(null, "item");
6654 serializer.attribute(null, "name", name);
6655 serializer.endTag(null, "item");
6656 }
6657 }
6658 }
6659 serializer.endTag(null, "perms");
6660 serializer.endTag(null, "updated-package");
6661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006662
6663 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006664 throws java.io.IOException {
6665 serializer.startTag(null, "package");
6666 serializer.attribute(null, "name", pkg.name);
6667 serializer.attribute(null, "codePath", pkg.codePathString);
6668 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6669 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6670 }
6671 serializer.attribute(null, "system",
6672 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6673 ? "true" : "false");
6674 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006675 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006676 if (pkg.sharedUser == null) {
6677 serializer.attribute(null, "userId",
6678 Integer.toString(pkg.userId));
6679 } else {
6680 serializer.attribute(null, "sharedUserId",
6681 Integer.toString(pkg.userId));
6682 }
6683 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6684 serializer.attribute(null, "enabled",
6685 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6686 ? "true" : "false");
6687 }
6688 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6689 serializer.attribute(null, "installStatus", "false");
6690 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006691 if (pkg.installerPackageName != null) {
6692 serializer.attribute(null, "installer", pkg.installerPackageName);
6693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6695 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6696 serializer.startTag(null, "perms");
6697 if (pkg.sharedUser == null) {
6698 // If this is a shared user, the permissions will
6699 // be written there. We still need to write an
6700 // empty permissions list so permissionsFixed will
6701 // be set.
6702 for (final String name : pkg.grantedPermissions) {
6703 serializer.startTag(null, "item");
6704 serializer.attribute(null, "name", name);
6705 serializer.endTag(null, "item");
6706 }
6707 }
6708 serializer.endTag(null, "perms");
6709 }
6710 if (pkg.disabledComponents.size() > 0) {
6711 serializer.startTag(null, "disabled-components");
6712 for (final String name : pkg.disabledComponents) {
6713 serializer.startTag(null, "item");
6714 serializer.attribute(null, "name", name);
6715 serializer.endTag(null, "item");
6716 }
6717 serializer.endTag(null, "disabled-components");
6718 }
6719 if (pkg.enabledComponents.size() > 0) {
6720 serializer.startTag(null, "enabled-components");
6721 for (final String name : pkg.enabledComponents) {
6722 serializer.startTag(null, "item");
6723 serializer.attribute(null, "name", name);
6724 serializer.endTag(null, "item");
6725 }
6726 serializer.endTag(null, "enabled-components");
6727 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 serializer.endTag(null, "package");
6730 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 void writePermission(XmlSerializer serializer, BasePermission bp)
6733 throws XmlPullParserException, java.io.IOException {
6734 if (bp.type != BasePermission.TYPE_BUILTIN
6735 && bp.sourcePackage != null) {
6736 serializer.startTag(null, "item");
6737 serializer.attribute(null, "name", bp.name);
6738 serializer.attribute(null, "package", bp.sourcePackage);
6739 if (DEBUG_SETTINGS) Log.v(TAG,
6740 "Writing perm: name=" + bp.name + " type=" + bp.type);
6741 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6742 PermissionInfo pi = bp.perm != null ? bp.perm.info
6743 : bp.pendingInfo;
6744 if (pi != null) {
6745 serializer.attribute(null, "type", "dynamic");
6746 if (pi.icon != 0) {
6747 serializer.attribute(null, "icon",
6748 Integer.toString(pi.icon));
6749 }
6750 if (pi.nonLocalizedLabel != null) {
6751 serializer.attribute(null, "label",
6752 pi.nonLocalizedLabel.toString());
6753 }
6754 if (pi.protectionLevel !=
6755 PermissionInfo.PROTECTION_NORMAL) {
6756 serializer.attribute(null, "protection",
6757 Integer.toString(pi.protectionLevel));
6758 }
6759 }
6760 }
6761 serializer.endTag(null, "item");
6762 }
6763 }
6764
6765 String getReadMessagesLP() {
6766 return mReadMessages.toString();
6767 }
6768
Oscar Montemayora8529f62009-11-18 10:14:20 -08006769 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006770 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6771 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006772 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006773 while(its.hasNext()) {
6774 String key = its.next();
6775 PackageSetting ps = mPackages.get(key);
6776 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006777 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 }
6779 }
6780 return ret;
6781 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006783 boolean readLP() {
6784 FileInputStream str = null;
6785 if (mBackupSettingsFilename.exists()) {
6786 try {
6787 str = new FileInputStream(mBackupSettingsFilename);
6788 mReadMessages.append("Reading from backup settings file\n");
6789 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006790 if (mSettingsFilename.exists()) {
6791 // If both the backup and settings file exist, we
6792 // ignore the settings since it might have been
6793 // corrupted.
6794 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6795 mSettingsFilename.delete();
6796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006797 } catch (java.io.IOException e) {
6798 // We'll try for the normal settings file.
6799 }
6800 }
6801
6802 mPastSignatures.clear();
6803
6804 try {
6805 if (str == null) {
6806 if (!mSettingsFilename.exists()) {
6807 mReadMessages.append("No settings file found\n");
6808 Log.i(TAG, "No current settings file!");
6809 return false;
6810 }
6811 str = new FileInputStream(mSettingsFilename);
6812 }
6813 XmlPullParser parser = Xml.newPullParser();
6814 parser.setInput(str, null);
6815
6816 int type;
6817 while ((type=parser.next()) != XmlPullParser.START_TAG
6818 && type != XmlPullParser.END_DOCUMENT) {
6819 ;
6820 }
6821
6822 if (type != XmlPullParser.START_TAG) {
6823 mReadMessages.append("No start tag found in settings file\n");
6824 Log.e(TAG, "No start tag found in package manager settings");
6825 return false;
6826 }
6827
6828 int outerDepth = parser.getDepth();
6829 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6830 && (type != XmlPullParser.END_TAG
6831 || parser.getDepth() > outerDepth)) {
6832 if (type == XmlPullParser.END_TAG
6833 || type == XmlPullParser.TEXT) {
6834 continue;
6835 }
6836
6837 String tagName = parser.getName();
6838 if (tagName.equals("package")) {
6839 readPackageLP(parser);
6840 } else if (tagName.equals("permissions")) {
6841 readPermissionsLP(mPermissions, parser);
6842 } else if (tagName.equals("permission-trees")) {
6843 readPermissionsLP(mPermissionTrees, parser);
6844 } else if (tagName.equals("shared-user")) {
6845 readSharedUserLP(parser);
6846 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006847 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006848 } else if (tagName.equals("preferred-activities")) {
6849 readPreferredActivitiesLP(parser);
6850 } else if(tagName.equals("updated-package")) {
6851 readDisabledSysPackageLP(parser);
6852 } else {
6853 Log.w(TAG, "Unknown element under <packages>: "
6854 + parser.getName());
6855 XmlUtils.skipCurrentTag(parser);
6856 }
6857 }
6858
6859 str.close();
6860
6861 } catch(XmlPullParserException e) {
6862 mReadMessages.append("Error reading: " + e.toString());
6863 Log.e(TAG, "Error reading package manager settings", e);
6864
6865 } catch(java.io.IOException e) {
6866 mReadMessages.append("Error reading: " + e.toString());
6867 Log.e(TAG, "Error reading package manager settings", e);
6868
6869 }
6870
6871 int N = mPendingPackages.size();
6872 for (int i=0; i<N; i++) {
6873 final PendingPackage pp = mPendingPackages.get(i);
6874 Object idObj = getUserIdLP(pp.sharedId);
6875 if (idObj != null && idObj instanceof SharedUserSetting) {
6876 PackageSetting p = getPackageLP(pp.name,
6877 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006878 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 if (p == null) {
6880 Log.w(TAG, "Unable to create application package for "
6881 + pp.name);
6882 continue;
6883 }
6884 p.copyFrom(pp);
6885 } else if (idObj != null) {
6886 String msg = "Bad package setting: package " + pp.name
6887 + " has shared uid " + pp.sharedId
6888 + " that is not a shared uid\n";
6889 mReadMessages.append(msg);
6890 Log.e(TAG, msg);
6891 } else {
6892 String msg = "Bad package setting: package " + pp.name
6893 + " has shared uid " + pp.sharedId
6894 + " that is not defined\n";
6895 mReadMessages.append(msg);
6896 Log.e(TAG, msg);
6897 }
6898 }
6899 mPendingPackages.clear();
6900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006901 mReadMessages.append("Read completed successfully: "
6902 + mPackages.size() + " packages, "
6903 + mSharedUsers.size() + " shared uids\n");
6904
6905 return true;
6906 }
6907
6908 private int readInt(XmlPullParser parser, String ns, String name,
6909 int defValue) {
6910 String v = parser.getAttributeValue(ns, name);
6911 try {
6912 if (v == null) {
6913 return defValue;
6914 }
6915 return Integer.parseInt(v);
6916 } catch (NumberFormatException e) {
6917 reportSettingsProblem(Log.WARN,
6918 "Error in package manager settings: attribute " +
6919 name + " has bad integer value " + v + " at "
6920 + parser.getPositionDescription());
6921 }
6922 return defValue;
6923 }
6924
6925 private void readPermissionsLP(HashMap<String, BasePermission> out,
6926 XmlPullParser parser)
6927 throws IOException, XmlPullParserException {
6928 int outerDepth = parser.getDepth();
6929 int type;
6930 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6931 && (type != XmlPullParser.END_TAG
6932 || parser.getDepth() > outerDepth)) {
6933 if (type == XmlPullParser.END_TAG
6934 || type == XmlPullParser.TEXT) {
6935 continue;
6936 }
6937
6938 String tagName = parser.getName();
6939 if (tagName.equals("item")) {
6940 String name = parser.getAttributeValue(null, "name");
6941 String sourcePackage = parser.getAttributeValue(null, "package");
6942 String ptype = parser.getAttributeValue(null, "type");
6943 if (name != null && sourcePackage != null) {
6944 boolean dynamic = "dynamic".equals(ptype);
6945 BasePermission bp = new BasePermission(name, sourcePackage,
6946 dynamic
6947 ? BasePermission.TYPE_DYNAMIC
6948 : BasePermission.TYPE_NORMAL);
6949 if (dynamic) {
6950 PermissionInfo pi = new PermissionInfo();
6951 pi.packageName = sourcePackage.intern();
6952 pi.name = name.intern();
6953 pi.icon = readInt(parser, null, "icon", 0);
6954 pi.nonLocalizedLabel = parser.getAttributeValue(
6955 null, "label");
6956 pi.protectionLevel = readInt(parser, null, "protection",
6957 PermissionInfo.PROTECTION_NORMAL);
6958 bp.pendingInfo = pi;
6959 }
6960 out.put(bp.name, bp);
6961 } else {
6962 reportSettingsProblem(Log.WARN,
6963 "Error in package manager settings: permissions has"
6964 + " no name at " + parser.getPositionDescription());
6965 }
6966 } else {
6967 reportSettingsProblem(Log.WARN,
6968 "Unknown element reading permissions: "
6969 + parser.getName() + " at "
6970 + parser.getPositionDescription());
6971 }
6972 XmlUtils.skipCurrentTag(parser);
6973 }
6974 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 private void readDisabledSysPackageLP(XmlPullParser parser)
6977 throws XmlPullParserException, IOException {
6978 String name = parser.getAttributeValue(null, "name");
6979 String codePathStr = parser.getAttributeValue(null, "codePath");
6980 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6981 if(resourcePathStr == null) {
6982 resourcePathStr = codePathStr;
6983 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006984 String version = parser.getAttributeValue(null, "version");
6985 int versionCode = 0;
6986 if (version != null) {
6987 try {
6988 versionCode = Integer.parseInt(version);
6989 } catch (NumberFormatException e) {
6990 }
6991 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 int pkgFlags = 0;
6994 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006995 PackageSetting ps = new PackageSetting(name,
6996 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006997 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 String timeStampStr = parser.getAttributeValue(null, "ts");
6999 if (timeStampStr != null) {
7000 try {
7001 long timeStamp = Long.parseLong(timeStampStr);
7002 ps.setTimeStamp(timeStamp, timeStampStr);
7003 } catch (NumberFormatException e) {
7004 }
7005 }
7006 String idStr = parser.getAttributeValue(null, "userId");
7007 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7008 if(ps.userId <= 0) {
7009 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7010 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7011 }
7012 int outerDepth = parser.getDepth();
7013 int type;
7014 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7015 && (type != XmlPullParser.END_TAG
7016 || parser.getDepth() > outerDepth)) {
7017 if (type == XmlPullParser.END_TAG
7018 || type == XmlPullParser.TEXT) {
7019 continue;
7020 }
7021
7022 String tagName = parser.getName();
7023 if (tagName.equals("perms")) {
7024 readGrantedPermissionsLP(parser,
7025 ps.grantedPermissions);
7026 } else {
7027 reportSettingsProblem(Log.WARN,
7028 "Unknown element under <updated-package>: "
7029 + parser.getName());
7030 XmlUtils.skipCurrentTag(parser);
7031 }
7032 }
7033 mDisabledSysPackages.put(name, ps);
7034 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 private void readPackageLP(XmlPullParser parser)
7037 throws XmlPullParserException, IOException {
7038 String name = null;
7039 String idStr = null;
7040 String sharedIdStr = null;
7041 String codePathStr = null;
7042 String resourcePathStr = null;
7043 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007044 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 int pkgFlags = 0;
7046 String timeStampStr;
7047 long timeStamp = 0;
7048 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007049 String version = null;
7050 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 try {
7052 name = parser.getAttributeValue(null, "name");
7053 idStr = parser.getAttributeValue(null, "userId");
7054 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7055 codePathStr = parser.getAttributeValue(null, "codePath");
7056 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007057 version = parser.getAttributeValue(null, "version");
7058 if (version != null) {
7059 try {
7060 versionCode = Integer.parseInt(version);
7061 } catch (NumberFormatException e) {
7062 }
7063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007065 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 if (systemStr != null) {
7067 if ("true".equals(systemStr)) {
7068 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7069 }
7070 } else {
7071 // Old settings that don't specify system... just treat
7072 // them as system, good enough.
7073 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7074 }
7075 timeStampStr = parser.getAttributeValue(null, "ts");
7076 if (timeStampStr != null) {
7077 try {
7078 timeStamp = Long.parseLong(timeStampStr);
7079 } catch (NumberFormatException e) {
7080 }
7081 }
7082 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7083 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7084 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7085 if (resourcePathStr == null) {
7086 resourcePathStr = codePathStr;
7087 }
7088 if (name == null) {
7089 reportSettingsProblem(Log.WARN,
7090 "Error in package manager settings: <package> has no name at "
7091 + parser.getPositionDescription());
7092 } else if (codePathStr == null) {
7093 reportSettingsProblem(Log.WARN,
7094 "Error in package manager settings: <package> has no codePath at "
7095 + parser.getPositionDescription());
7096 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007097 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007098 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007099 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7100 + ": userId=" + userId + " pkg=" + packageSetting);
7101 if (packageSetting == null) {
7102 reportSettingsProblem(Log.ERROR,
7103 "Failure adding uid " + userId
7104 + " while parsing settings at "
7105 + parser.getPositionDescription());
7106 } else {
7107 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7108 }
7109 } else if (sharedIdStr != null) {
7110 userId = sharedIdStr != null
7111 ? Integer.parseInt(sharedIdStr) : 0;
7112 if (userId > 0) {
7113 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007114 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7116 mPendingPackages.add((PendingPackage) packageSetting);
7117 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7118 + ": sharedUserId=" + userId + " pkg="
7119 + packageSetting);
7120 } else {
7121 reportSettingsProblem(Log.WARN,
7122 "Error in package manager settings: package "
7123 + name + " has bad sharedId " + sharedIdStr
7124 + " at " + parser.getPositionDescription());
7125 }
7126 } else {
7127 reportSettingsProblem(Log.WARN,
7128 "Error in package manager settings: package "
7129 + name + " has bad userId " + idStr + " at "
7130 + parser.getPositionDescription());
7131 }
7132 } catch (NumberFormatException e) {
7133 reportSettingsProblem(Log.WARN,
7134 "Error in package manager settings: package "
7135 + name + " has bad userId " + idStr + " at "
7136 + parser.getPositionDescription());
7137 }
7138 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007139 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 final String enabledStr = parser.getAttributeValue(null, "enabled");
7141 if (enabledStr != null) {
7142 if (enabledStr.equalsIgnoreCase("true")) {
7143 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7144 } else if (enabledStr.equalsIgnoreCase("false")) {
7145 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7146 } else if (enabledStr.equalsIgnoreCase("default")) {
7147 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7148 } else {
7149 reportSettingsProblem(Log.WARN,
7150 "Error in package manager settings: package "
7151 + name + " has bad enabled value: " + idStr
7152 + " at " + parser.getPositionDescription());
7153 }
7154 } else {
7155 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7156 }
7157 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7158 if (installStatusStr != null) {
7159 if (installStatusStr.equalsIgnoreCase("false")) {
7160 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7161 } else {
7162 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7163 }
7164 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007166 int outerDepth = parser.getDepth();
7167 int type;
7168 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7169 && (type != XmlPullParser.END_TAG
7170 || parser.getDepth() > outerDepth)) {
7171 if (type == XmlPullParser.END_TAG
7172 || type == XmlPullParser.TEXT) {
7173 continue;
7174 }
7175
7176 String tagName = parser.getName();
7177 if (tagName.equals("disabled-components")) {
7178 readDisabledComponentsLP(packageSetting, parser);
7179 } else if (tagName.equals("enabled-components")) {
7180 readEnabledComponentsLP(packageSetting, parser);
7181 } else if (tagName.equals("sigs")) {
7182 packageSetting.signatures.readXml(parser, mPastSignatures);
7183 } else if (tagName.equals("perms")) {
7184 readGrantedPermissionsLP(parser,
7185 packageSetting.loadedPermissions);
7186 packageSetting.permissionsFixed = true;
7187 } else {
7188 reportSettingsProblem(Log.WARN,
7189 "Unknown element under <package>: "
7190 + parser.getName());
7191 XmlUtils.skipCurrentTag(parser);
7192 }
7193 }
7194 } else {
7195 XmlUtils.skipCurrentTag(parser);
7196 }
7197 }
7198
7199 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7200 XmlPullParser parser)
7201 throws IOException, XmlPullParserException {
7202 int outerDepth = parser.getDepth();
7203 int type;
7204 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7205 && (type != XmlPullParser.END_TAG
7206 || parser.getDepth() > outerDepth)) {
7207 if (type == XmlPullParser.END_TAG
7208 || type == XmlPullParser.TEXT) {
7209 continue;
7210 }
7211
7212 String tagName = parser.getName();
7213 if (tagName.equals("item")) {
7214 String name = parser.getAttributeValue(null, "name");
7215 if (name != null) {
7216 packageSetting.disabledComponents.add(name.intern());
7217 } else {
7218 reportSettingsProblem(Log.WARN,
7219 "Error in package manager settings: <disabled-components> has"
7220 + " no name at " + parser.getPositionDescription());
7221 }
7222 } else {
7223 reportSettingsProblem(Log.WARN,
7224 "Unknown element under <disabled-components>: "
7225 + parser.getName());
7226 }
7227 XmlUtils.skipCurrentTag(parser);
7228 }
7229 }
7230
7231 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7232 XmlPullParser parser)
7233 throws IOException, XmlPullParserException {
7234 int outerDepth = parser.getDepth();
7235 int type;
7236 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7237 && (type != XmlPullParser.END_TAG
7238 || parser.getDepth() > outerDepth)) {
7239 if (type == XmlPullParser.END_TAG
7240 || type == XmlPullParser.TEXT) {
7241 continue;
7242 }
7243
7244 String tagName = parser.getName();
7245 if (tagName.equals("item")) {
7246 String name = parser.getAttributeValue(null, "name");
7247 if (name != null) {
7248 packageSetting.enabledComponents.add(name.intern());
7249 } else {
7250 reportSettingsProblem(Log.WARN,
7251 "Error in package manager settings: <enabled-components> has"
7252 + " no name at " + parser.getPositionDescription());
7253 }
7254 } else {
7255 reportSettingsProblem(Log.WARN,
7256 "Unknown element under <enabled-components>: "
7257 + parser.getName());
7258 }
7259 XmlUtils.skipCurrentTag(parser);
7260 }
7261 }
7262
7263 private void readSharedUserLP(XmlPullParser parser)
7264 throws XmlPullParserException, IOException {
7265 String name = null;
7266 String idStr = null;
7267 int pkgFlags = 0;
7268 SharedUserSetting su = null;
7269 try {
7270 name = parser.getAttributeValue(null, "name");
7271 idStr = parser.getAttributeValue(null, "userId");
7272 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7273 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7274 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7275 }
7276 if (name == null) {
7277 reportSettingsProblem(Log.WARN,
7278 "Error in package manager settings: <shared-user> has no name at "
7279 + parser.getPositionDescription());
7280 } else if (userId == 0) {
7281 reportSettingsProblem(Log.WARN,
7282 "Error in package manager settings: shared-user "
7283 + name + " has bad userId " + idStr + " at "
7284 + parser.getPositionDescription());
7285 } else {
7286 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7287 reportSettingsProblem(Log.ERROR,
7288 "Occurred while parsing settings at "
7289 + parser.getPositionDescription());
7290 }
7291 }
7292 } catch (NumberFormatException e) {
7293 reportSettingsProblem(Log.WARN,
7294 "Error in package manager settings: package "
7295 + name + " has bad userId " + idStr + " at "
7296 + parser.getPositionDescription());
7297 };
7298
7299 if (su != null) {
7300 int outerDepth = parser.getDepth();
7301 int type;
7302 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7303 && (type != XmlPullParser.END_TAG
7304 || parser.getDepth() > outerDepth)) {
7305 if (type == XmlPullParser.END_TAG
7306 || type == XmlPullParser.TEXT) {
7307 continue;
7308 }
7309
7310 String tagName = parser.getName();
7311 if (tagName.equals("sigs")) {
7312 su.signatures.readXml(parser, mPastSignatures);
7313 } else if (tagName.equals("perms")) {
7314 readGrantedPermissionsLP(parser, su.loadedPermissions);
7315 } else {
7316 reportSettingsProblem(Log.WARN,
7317 "Unknown element under <shared-user>: "
7318 + parser.getName());
7319 XmlUtils.skipCurrentTag(parser);
7320 }
7321 }
7322
7323 } else {
7324 XmlUtils.skipCurrentTag(parser);
7325 }
7326 }
7327
7328 private void readGrantedPermissionsLP(XmlPullParser parser,
7329 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7330 int outerDepth = parser.getDepth();
7331 int type;
7332 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7333 && (type != XmlPullParser.END_TAG
7334 || parser.getDepth() > outerDepth)) {
7335 if (type == XmlPullParser.END_TAG
7336 || type == XmlPullParser.TEXT) {
7337 continue;
7338 }
7339
7340 String tagName = parser.getName();
7341 if (tagName.equals("item")) {
7342 String name = parser.getAttributeValue(null, "name");
7343 if (name != null) {
7344 outPerms.add(name.intern());
7345 } else {
7346 reportSettingsProblem(Log.WARN,
7347 "Error in package manager settings: <perms> has"
7348 + " no name at " + parser.getPositionDescription());
7349 }
7350 } else {
7351 reportSettingsProblem(Log.WARN,
7352 "Unknown element under <perms>: "
7353 + parser.getName());
7354 }
7355 XmlUtils.skipCurrentTag(parser);
7356 }
7357 }
7358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007359 private void readPreferredActivitiesLP(XmlPullParser parser)
7360 throws XmlPullParserException, IOException {
7361 int outerDepth = parser.getDepth();
7362 int type;
7363 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7364 && (type != XmlPullParser.END_TAG
7365 || parser.getDepth() > outerDepth)) {
7366 if (type == XmlPullParser.END_TAG
7367 || type == XmlPullParser.TEXT) {
7368 continue;
7369 }
7370
7371 String tagName = parser.getName();
7372 if (tagName.equals("item")) {
7373 PreferredActivity pa = new PreferredActivity(parser);
7374 if (pa.mParseError == null) {
7375 mPreferredActivities.addFilter(pa);
7376 } else {
7377 reportSettingsProblem(Log.WARN,
7378 "Error in package manager settings: <preferred-activity> "
7379 + pa.mParseError + " at "
7380 + parser.getPositionDescription());
7381 }
7382 } else {
7383 reportSettingsProblem(Log.WARN,
7384 "Unknown element under <preferred-activities>: "
7385 + parser.getName());
7386 XmlUtils.skipCurrentTag(parser);
7387 }
7388 }
7389 }
7390
7391 // Returns -1 if we could not find an available UserId to assign
7392 private int newUserIdLP(Object obj) {
7393 // Let's be stupidly inefficient for now...
7394 final int N = mUserIds.size();
7395 for (int i=0; i<N; i++) {
7396 if (mUserIds.get(i) == null) {
7397 mUserIds.set(i, obj);
7398 return FIRST_APPLICATION_UID + i;
7399 }
7400 }
7401
7402 // None left?
7403 if (N >= MAX_APPLICATION_UIDS) {
7404 return -1;
7405 }
7406
7407 mUserIds.add(obj);
7408 return FIRST_APPLICATION_UID + N;
7409 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 public PackageSetting getDisabledSystemPkg(String name) {
7412 synchronized(mPackages) {
7413 PackageSetting ps = mDisabledSysPackages.get(name);
7414 return ps;
7415 }
7416 }
7417
7418 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7419 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7420 if (Config.LOGV) {
7421 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7422 + " componentName = " + componentInfo.name);
7423 Log.v(TAG, "enabledComponents: "
7424 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7425 Log.v(TAG, "disabledComponents: "
7426 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7427 }
7428 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7429 || ((componentInfo.enabled
7430 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7431 || (componentInfo.applicationInfo.enabled
7432 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7433 && !packageSettings.disabledComponents.contains(componentInfo.name))
7434 || packageSettings.enabledComponents.contains(componentInfo.name));
7435 }
7436 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007437
7438 // ------- apps on sdcard specific code -------
7439 static final boolean DEBUG_SD_INSTALL = false;
7440 final private String mSdEncryptKey = "none";
7441
7442 private MountService getMountService() {
7443 return (MountService) ServiceManager.getService("mount");
7444 }
7445
7446 private String createSdDir(File tmpPackageFile, String pkgName) {
7447 // Create mount point via MountService
7448 MountService mountService = getMountService();
7449 long len = tmpPackageFile.length();
7450 int mbLen = (int) (len/(1024*1024));
7451 if ((len - (mbLen * 1024 * 1024)) > 0) {
7452 mbLen++;
7453 }
7454 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
7455 String cachePath = null;
7456 // Remove any pending destroy messages
7457 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
7458 try {
7459 cachePath = mountService.createSecureContainer(pkgName,
7460 mbLen,
7461 "vfat", mSdEncryptKey, Process.SYSTEM_UID);
7462 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
7463 return cachePath;
7464 } catch(IllegalStateException e) {
7465 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7466 }
7467 // TODO just fail here and let the user delete later on.
7468 try {
7469 mountService.destroySecureContainer(pkgName);
7470 if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
7471 } catch(IllegalStateException e) {
7472 Log.e(TAG, "Failed to destroy existing cache: " + e);
7473 return null;
7474 }
7475 try {
7476 cachePath = mountService.createSecureContainer(pkgName,
7477 mbLen,
7478 "vfat", mSdEncryptKey, Process.SYSTEM_UID);
7479 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
7480 return cachePath;
7481 } catch(IllegalStateException e) {
7482 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7483 return null;
7484 }
7485 }
7486
7487 private String mountSdDir(String pkgName, int ownerUid) {
7488 try {
7489 return getMountService().mountSecureContainer(pkgName, mSdEncryptKey, ownerUid);
7490 } catch (IllegalStateException e) {
7491 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
7492 }
7493 return null;
7494 }
7495
7496 private String getSdDir(String pkgName) {
7497 String cachePath = null;
7498 try {
7499 cachePath = getMountService().getSecureContainerPath(pkgName);
7500 } catch (IllegalStateException e) {
7501 Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
7502 }
7503 return cachePath;
7504 }
7505
7506 private boolean finalizeSdDir(String pkgName) {
7507 try {
7508 getMountService().finalizeSecureContainer(pkgName);
7509 return true;
7510 } catch (IllegalStateException e) {
7511 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7512 return false;
7513 }
7514 }
7515
7516 private boolean destroySdDir(String pkgName) {
7517 try {
7518 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7519 // Don't have to send message again
7520 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
7521 }
7522 // We need to destroy right away
7523 getMountService().destroySecureContainer(pkgName);
7524 return true;
7525 } catch (IllegalStateException e) {
7526 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7527 return false;
7528 }
7529 }
7530
7531 private void sendDelayedDestroySdDir(String pkgName) {
7532 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7533 // Don't have to send message again
7534 return;
7535 }
7536 Message msg = mHandler.obtainMessage(DESTROY_SD_CONTAINER, pkgName);
7537 mHandler.sendMessageDelayed(msg, DESTROY_SD_CONTAINER_DELAY);
7538 }
7539
7540 public void updateExternalMediaStatus(boolean mediaStatus) {
7541 // TODO
7542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007543}