blob: 4b9b36637dae55d7b439de6ba54512bb171ffeaa [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 Amalapurapuaf8e9f42010-01-12 10:17:28 -08003989 }
3990 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02003991 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 res);
3993 updatedSettings = true;
3994 }
3995 }
3996
3997 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3998 // If we deleted an exisiting package, the old source and resource files that we
3999 // were keeping around in case we needed them (see below) can now be deleted
4000 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
4001 final ApplicationInfo installedPackageAppInfo =
4002 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004003 deletePackageResourcesLI(pkgName,
4004 !deletedPackageAppInfo.sourceDir
4005 .equals(installedPackageAppInfo.sourceDir)
4006 ? deletedPackageAppInfo.sourceDir : null,
4007 !deletedPackageAppInfo.publicSourceDir
4008 .equals(installedPackageAppInfo.publicSourceDir)
4009 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 //update signature on the new package setting
4011 //this should always succeed, since we checked the
4012 //signature earlier.
4013 synchronized(mPackages) {
4014 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4015 parseFlags, true);
4016 }
4017 } else {
4018 // remove package from internal structures. Note that we want deletePackageX to
4019 // delete the package data and cache directories that it created in
4020 // scanPackageLocked, unless those directories existed before we even tried to
4021 // install.
4022 if(updatedSettings) {
4023 deletePackageLI(
4024 pkgName, true,
4025 PackageManager.DONT_DELETE_DATA,
4026 res.removedInfo);
4027 }
4028 // Since we failed to install the new package we need to restore the old
4029 // package that we deleted.
4030 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004031 File restoreFile = new File(deletedPackage.mPath);
4032 if (restoreFile == null) {
4033 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4034 return;
4035 }
4036 File restoreTmpFile = createTempPackageFile();
4037 if (restoreTmpFile == null) {
4038 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
4039 return;
4040 }
4041 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
4042 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
4043 return;
4044 }
4045 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4046 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004047 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004048 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004050 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004051 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
4052 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4053 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 }
4056 }
4057 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004060 PackageParser.Package pkg,
4061 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004062 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 PackageParser.Package newPackage = null;
4064 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004065 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 PackageParser.PARSE_IS_SYSTEM;
4067 String packageName = deletedPackage.packageName;
4068 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4069 if (packageName == null) {
4070 Log.w(TAG, "Attempt to delete null packageName.");
4071 return;
4072 }
4073 PackageParser.Package oldPkg;
4074 PackageSetting oldPkgSetting;
4075 synchronized (mPackages) {
4076 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004077 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4079 (oldPkgSetting == null)) {
4080 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4081 return;
4082 }
4083 }
4084 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4085 res.removedInfo.removedPackage = packageName;
4086 // Remove existing system package
4087 removePackageLI(oldPkg, true);
4088 synchronized (mPackages) {
4089 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4090 }
4091
4092 // Successfully disabled the old package. Now proceed with re-installation
4093 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4094 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004095 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004097 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4099 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4100 }
4101 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004102 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004103 updatedSettings = true;
4104 }
4105
4106 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4107 //update signature on the new package setting
4108 //this should always succeed, since we checked the
4109 //signature earlier.
4110 synchronized(mPackages) {
4111 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4112 parseFlags, true);
4113 }
4114 } else {
4115 // Re installation failed. Restore old information
4116 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004117 if (newPackage != null) {
4118 removePackageLI(newPackage, true);
4119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004121 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004123 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 // Restore the old system information in Settings
4125 synchronized(mPackages) {
4126 if(updatedSettings) {
4127 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004128 mSettings.setInstallerPackageName(packageName,
4129 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 }
4131 mSettings.writeLP();
4132 }
4133 }
4134 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004135
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004136 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004137 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004138 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 synchronized (mPackages) {
4140 //write settings. the installStatus will be incomplete at this stage.
4141 //note that the new package setting would have already been
4142 //added to mPackages. It hasn't been persisted yet.
4143 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4144 mSettings.writeLP();
4145 }
4146
4147 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004148 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4149 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004151 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4153 return;
4154 }
4155 }
4156 // XXX There are probably some big issues here: upon doing
4157 // the rename, we have reached the point of no return (the
4158 // original .apk is gone!), so we can't fail. Yet... we can.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004159 File scanFile = new File(newPackage.mScanPath);
4160 if (!scanFile.renameTo(new File(newPackage.mPath))) {
4161 Log.e(TAG, "Couldn't move package file: " + newPackage.mScanPath + " to: " + newPackage.mPath);
4162 // TODO rename should work. Workaround
4163 if (!FileUtils.copyFile(scanFile, new File(newPackage.mPath))) {
4164 Log.e(TAG, "Couldn't move package file to: " + newPackage.mPath);
4165 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004168 res.returnCode = setPermissionsLI(newPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4170 return;
4171 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004172 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 }
4174 }
4175 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4176 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004177 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
4179 }
4180
4181 synchronized (mPackages) {
4182 grantPermissionsLP(newPackage, true);
4183 res.name = pkgName;
4184 res.uid = newPackage.applicationInfo.uid;
4185 res.pkg = newPackage;
4186 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004187 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004188 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4189 //to update install status
4190 mSettings.writeLP();
4191 }
4192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004193
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004194 private File copyTempInstallFile(Uri pPackageURI,
4195 PackageInstalledInfo res) {
4196 File tmpPackageFile = createTempPackageFile();
4197 int retCode = PackageManager.INSTALL_SUCCEEDED;
4198 if (tmpPackageFile == null) {
4199 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4200 return null;
4201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004203 if (pPackageURI.getScheme().equals("file")) {
4204 final File srcPackageFile = new File(pPackageURI.getPath());
4205 // We copy the source package file to a temp file and then rename it to the
4206 // destination file in order to eliminate a window where the package directory
4207 // scanner notices the new package file but it's not completely copied yet.
4208 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4209 Log.e(TAG, "Couldn't copy package file to temp file.");
4210 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004211 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004212 } else if (pPackageURI.getScheme().equals("content")) {
4213 ParcelFileDescriptor fd = null;
4214 try {
4215 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4216 } catch (FileNotFoundException e) {
4217 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4218 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4219 }
4220 if (fd == null) {
4221 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4222 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4223 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004224 if (Config.LOGV) {
4225 Log.v(TAG, "Opened file descriptor from download service.");
4226 }
4227 ParcelFileDescriptor.AutoCloseInputStream
4228 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4229 // We copy the source package file to a temp file and then rename it to the
4230 // destination file in order to eliminate a window where the package directory
4231 // scanner notices the new package file but it's not completely copied yet.
4232 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4233 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004234 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004237 } else {
4238 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4239 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4240 }
4241
4242 res.returnCode = retCode;
4243 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4244 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4245 tmpPackageFile.delete();
4246 }
4247 return null;
4248 }
4249 return tmpPackageFile;
4250 }
4251
4252 private void installPackageLI(Uri pPackageURI,
4253 int pFlags, boolean newInstall, String installerPackageName,
4254 File tmpPackageFile, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004255 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
4256 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004257 boolean replacingExistingPackage = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004258 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
4259 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004260 // Result object to be returned
4261 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4262
4263 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 // Retrieve PackageSettings and parse package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004265 int parseFlags = PackageParser.PARSE_CHATTY |
4266 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
4267 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004268 parseFlags |= mDefParseFlags;
4269 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4270 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004271 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004272 null, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273 if (pkg == null) {
4274 res.returnCode = pp.getParseError();
4275 break main_flow;
4276 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004277 String pkgName = res.name = pkg.packageName;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004278 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4279 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4280 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4281 break main_flow;
4282 }
4283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004284 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4285 res.returnCode = pp.getParseError();
4286 break main_flow;
4287 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004289 synchronized (mPackages) {
4290 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004291 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 && mPackages.containsKey(pkgName)) {
4293 replacingExistingPackage = true;
4294 }
4295 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 if(replacingExistingPackage) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004298 replacePackageLI(pkg, parseFlags, scanMode,
4299 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004301 installNewPackageLI(pkg, parseFlags, scanMode,
4302 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 }
4304 } finally {
4305 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4306 tmpPackageFile.delete();
4307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 }
4309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004310
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004311 private int setPermissionsLI(PackageParser.Package newPackage) {
4312 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 int retCode;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004314 if ((newPackage.applicationInfo.flags
4315 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
4316 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 try {
4318 extractPublicFiles(newPackage, destResourceFile);
4319 } catch (IOException e) {
4320 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4321 " forward-locked app.");
4322 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4323 } finally {
4324 //TODO clean up the extracted public files
4325 }
4326 if (mInstaller != null) {
4327 retCode = mInstaller.setForwardLockPerm(pkgName,
4328 newPackage.applicationInfo.uid);
4329 } else {
4330 final int filePermissions =
4331 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004332 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004333 newPackage.applicationInfo.uid);
4334 }
4335 } else {
4336 final int filePermissions =
4337 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4338 |FileUtils.S_IROTH;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004339 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 }
4341 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004342 Log.e(TAG, "Couldn't set new package file permissions for " +
4343 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 + ". The return code was: " + retCode);
4345 }
4346 return PackageManager.INSTALL_SUCCEEDED;
4347 }
4348
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004349 private boolean isForwardLocked(PackageParser.Package pkg) {
4350 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 }
4352
4353 private void extractPublicFiles(PackageParser.Package newPackage,
4354 File publicZipFile) throws IOException {
4355 final ZipOutputStream publicZipOutStream =
4356 new ZipOutputStream(new FileOutputStream(publicZipFile));
4357 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4358
4359 // Copy manifest, resources.arsc and res directory to public zip
4360
4361 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4362 while (privateZipEntries.hasMoreElements()) {
4363 final ZipEntry zipEntry = privateZipEntries.nextElement();
4364 final String zipEntryName = zipEntry.getName();
4365 if ("AndroidManifest.xml".equals(zipEntryName)
4366 || "resources.arsc".equals(zipEntryName)
4367 || zipEntryName.startsWith("res/")) {
4368 try {
4369 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4370 } catch (IOException e) {
4371 try {
4372 publicZipOutStream.close();
4373 throw e;
4374 } finally {
4375 publicZipFile.delete();
4376 }
4377 }
4378 }
4379 }
4380
4381 publicZipOutStream.close();
4382 FileUtils.setPermissions(
4383 publicZipFile.getAbsolutePath(),
4384 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4385 -1, -1);
4386 }
4387
4388 private static void copyZipEntry(ZipEntry zipEntry,
4389 ZipFile inZipFile,
4390 ZipOutputStream outZipStream) throws IOException {
4391 byte[] buffer = new byte[4096];
4392 int num;
4393
4394 ZipEntry newEntry;
4395 if (zipEntry.getMethod() == ZipEntry.STORED) {
4396 // Preserve the STORED method of the input entry.
4397 newEntry = new ZipEntry(zipEntry);
4398 } else {
4399 // Create a new entry so that the compressed len is recomputed.
4400 newEntry = new ZipEntry(zipEntry.getName());
4401 }
4402 outZipStream.putNextEntry(newEntry);
4403
4404 InputStream data = inZipFile.getInputStream(zipEntry);
4405 while ((num = data.read(buffer)) > 0) {
4406 outZipStream.write(buffer, 0, num);
4407 }
4408 outZipStream.flush();
4409 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 private void deleteTempPackageFiles() {
4412 FilenameFilter filter = new FilenameFilter() {
4413 public boolean accept(File dir, String name) {
4414 return name.startsWith("vmdl") && name.endsWith(".tmp");
4415 }
4416 };
4417 String tmpFilesList[] = mAppInstallDir.list(filter);
4418 if(tmpFilesList == null) {
4419 return;
4420 }
4421 for(int i = 0; i < tmpFilesList.length; i++) {
4422 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4423 tmpFile.delete();
4424 }
4425 }
4426
4427 private File createTempPackageFile() {
4428 File tmpPackageFile;
4429 try {
4430 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4431 } catch (IOException e) {
4432 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4433 return null;
4434 }
4435 try {
4436 FileUtils.setPermissions(
4437 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4438 -1, -1);
4439 } catch (IOException e) {
4440 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4441 return null;
4442 }
4443 return tmpPackageFile;
4444 }
4445
4446 public void deletePackage(final String packageName,
4447 final IPackageDeleteObserver observer,
4448 final int flags) {
4449 mContext.enforceCallingOrSelfPermission(
4450 android.Manifest.permission.DELETE_PACKAGES, null);
4451 // Queue up an async operation since the package deletion may take a little while.
4452 mHandler.post(new Runnable() {
4453 public void run() {
4454 mHandler.removeCallbacks(this);
4455 final boolean succeded = deletePackageX(packageName, true, true, flags);
4456 if (observer != null) {
4457 try {
4458 observer.packageDeleted(succeded);
4459 } catch (RemoteException e) {
4460 Log.i(TAG, "Observer no longer exists.");
4461 } //end catch
4462 } //end if
4463 } //end run
4464 });
4465 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 /**
4468 * This method is an internal method that could be get invoked either
4469 * to delete an installed package or to clean up a failed installation.
4470 * After deleting an installed package, a broadcast is sent to notify any
4471 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004472 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 * installation wouldn't have sent the initial broadcast either
4474 * The key steps in deleting a package are
4475 * deleting the package information in internal structures like mPackages,
4476 * deleting the packages base directories through installd
4477 * updating mSettings to reflect current status
4478 * persisting settings for later use
4479 * sending a broadcast if necessary
4480 */
4481
4482 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4483 boolean deleteCodeAndResources, int flags) {
4484 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004485 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486
4487 synchronized (mInstallLock) {
4488 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4489 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004492 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4493 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4494
4495 // If the removed package was a system update, the old system packaged
4496 // was re-enabled; we need to broadcast this information
4497 if (systemUpdate) {
4498 Bundle extras = new Bundle(1);
4499 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4500 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4501
4502 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4503 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
4506 return res;
4507 }
4508
4509 static class PackageRemovedInfo {
4510 String removedPackage;
4511 int uid = -1;
4512 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004513 boolean isRemovedPackageSystemUpdate = false;
4514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 void sendBroadcast(boolean fullRemove, boolean replacing) {
4516 Bundle extras = new Bundle(1);
4517 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4518 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4519 if (replacing) {
4520 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4521 }
4522 if (removedPackage != null) {
4523 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4524 }
4525 if (removedUid >= 0) {
4526 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4527 }
4528 }
4529 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 /*
4532 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4533 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004534 * 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 -08004535 * delete a partially installed application.
4536 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004537 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 int flags) {
4539 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004540 if (outInfo != null) {
4541 outInfo.removedPackage = packageName;
4542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004543 removePackageLI(p, true);
4544 // Retrieve object to delete permissions for shared user later on
4545 PackageSetting deletedPs;
4546 synchronized (mPackages) {
4547 deletedPs = mSettings.mPackages.get(packageName);
4548 }
4549 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004550 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004552 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553 if (retCode < 0) {
4554 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4555 + packageName + ", retcode=" + retCode);
4556 // we don't consider this to be a failure of the core package deletion
4557 }
4558 } else {
4559 //for emulator
4560 PackageParser.Package pkg = mPackages.get(packageName);
4561 File dataDir = new File(pkg.applicationInfo.dataDir);
4562 dataDir.delete();
4563 }
4564 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004565 if (outInfo != null) {
4566 outInfo.removedUid = mSettings.removePackageLP(packageName);
4567 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 }
4569 }
4570 synchronized (mPackages) {
4571 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4572 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004573 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 }
4575 // Save settings now
4576 mSettings.writeLP ();
4577 }
4578 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004580 /*
4581 * Tries to delete system package.
4582 */
4583 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004584 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004585 ApplicationInfo applicationInfo = p.applicationInfo;
4586 //applicable for non-partially installed applications only
4587 if (applicationInfo == null) {
4588 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4589 return false;
4590 }
4591 PackageSetting ps = null;
4592 // Confirm if the system package has been updated
4593 // An updated system app can be deleted. This will also have to restore
4594 // the system pkg from system partition
4595 synchronized (mPackages) {
4596 ps = mSettings.getDisabledSystemPkg(p.packageName);
4597 }
4598 if (ps == null) {
4599 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4600 return false;
4601 } else {
4602 Log.i(TAG, "Deleting system pkg from data partition");
4603 }
4604 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004605 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004606 boolean deleteCodeAndResources = false;
4607 if (ps.versionCode < p.mVersionCode) {
4608 // Delete code and resources for downgrades
4609 deleteCodeAndResources = true;
4610 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4611 flags &= ~PackageManager.DONT_DELETE_DATA;
4612 }
4613 } else {
4614 // Preserve data by setting flag
4615 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4616 flags |= PackageManager.DONT_DELETE_DATA;
4617 }
4618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4620 if (!ret) {
4621 return false;
4622 }
4623 synchronized (mPackages) {
4624 // Reinstate the old system package
4625 mSettings.enableSystemPackageLP(p.packageName);
4626 }
4627 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004628 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004630 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004632 if (newPkg == null) {
4633 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4634 return false;
4635 }
4636 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004637 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 mSettings.writeLP();
4639 }
4640 return true;
4641 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004642
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004643 private void deletePackageResourcesLI(String packageName,
4644 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004645 if (sourceDir != null) {
4646 File sourceFile = new File(sourceDir);
4647 if (!sourceFile.exists()) {
4648 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4649 }
4650 // Delete application's code and resources
4651 sourceFile.delete();
4652 if (mInstaller != null) {
4653 int retCode = mInstaller.rmdex(sourceFile.toString());
4654 if (retCode < 0) {
4655 Log.w(TAG, "Couldn't remove dex file for package: "
4656 + packageName + " at location "
4657 + sourceFile.toString() + ", retcode=" + retCode);
4658 // we don't consider this to be a failure of the core package deletion
4659 }
4660 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004661 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004662 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4663 final File publicSourceFile = new File(publicSourceDir);
4664 if (!publicSourceFile.exists()) {
4665 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4666 }
4667 if (publicSourceFile.exists()) {
4668 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004669 }
4670 }
4671 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004673 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4674 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4675 ApplicationInfo applicationInfo = p.applicationInfo;
4676 if (applicationInfo == null) {
4677 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4678 return false;
4679 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004680 if (outInfo != null) {
4681 outInfo.uid = applicationInfo.uid;
4682 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683
4684 // Delete package data from internal structures and also remove data if flag is set
4685 removePackageDataLI(p, outInfo, flags);
4686
4687 // Delete application code and resources
4688 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004689 deletePackageResourcesLI(applicationInfo.packageName,
4690 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 }
4692 return true;
4693 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 /*
4696 * This method handles package deletion in general
4697 */
4698 private boolean deletePackageLI(String packageName,
4699 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4700 if (packageName == null) {
4701 Log.w(TAG, "Attempt to delete null packageName.");
4702 return false;
4703 }
4704 PackageParser.Package p;
4705 boolean dataOnly = false;
4706 synchronized (mPackages) {
4707 p = mPackages.get(packageName);
4708 if (p == null) {
4709 //this retrieves partially installed apps
4710 dataOnly = true;
4711 PackageSetting ps = mSettings.mPackages.get(packageName);
4712 if (ps == null) {
4713 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4714 return false;
4715 }
4716 p = ps.pkg;
4717 }
4718 }
4719 if (p == null) {
4720 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4721 return false;
4722 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (dataOnly) {
4725 // Delete application data first
4726 removePackageDataLI(p, outInfo, flags);
4727 return true;
4728 }
4729 // At this point the package should have ApplicationInfo associated with it
4730 if (p.applicationInfo == null) {
4731 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4732 return false;
4733 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004734 boolean onSd = (p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0;
4735 // Mount sd container if needed
4736 if (onSd) {
4737 // TODO Better error handling from MountService api later
4738 mountSdDir(p.packageName, Process.SYSTEM_UID) ;
4739 }
4740 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004741 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4742 Log.i(TAG, "Removing system package:"+p.packageName);
4743 // When an updated system application is deleted we delete the existing resources as well and
4744 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004745 ret = deleteSystemPackageLI(p, flags, outInfo);
4746 } else {
4747 Log.i(TAG, "Removing non-system package:"+p.packageName);
4748 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004750 if (ret && onSd) {
4751 // Post a delayed destroy on the container since there might
4752 // be active processes holding open file handles to package
4753 // resources which will get killed by the process killer when
4754 // destroying the container. This might even kill the current
4755 // process and crash the system. Delay the destroy a bit so
4756 // that the active processes get to handle the uninstall broadcasts.
4757 sendDelayedDestroySdDir(packageName);
4758 }
4759 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004760 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 public void clearApplicationUserData(final String packageName,
4763 final IPackageDataObserver observer) {
4764 mContext.enforceCallingOrSelfPermission(
4765 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4766 // Queue up an async operation since the package deletion may take a little while.
4767 mHandler.post(new Runnable() {
4768 public void run() {
4769 mHandler.removeCallbacks(this);
4770 final boolean succeeded;
4771 synchronized (mInstallLock) {
4772 succeeded = clearApplicationUserDataLI(packageName);
4773 }
4774 if (succeeded) {
4775 // invoke DeviceStorageMonitor's update method to clear any notifications
4776 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4777 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4778 if (dsm != null) {
4779 dsm.updateMemory();
4780 }
4781 }
4782 if(observer != null) {
4783 try {
4784 observer.onRemoveCompleted(packageName, succeeded);
4785 } catch (RemoteException e) {
4786 Log.i(TAG, "Observer no longer exists.");
4787 }
4788 } //end if observer
4789 } //end run
4790 });
4791 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 private boolean clearApplicationUserDataLI(String packageName) {
4794 if (packageName == null) {
4795 Log.w(TAG, "Attempt to delete null packageName.");
4796 return false;
4797 }
4798 PackageParser.Package p;
4799 boolean dataOnly = false;
4800 synchronized (mPackages) {
4801 p = mPackages.get(packageName);
4802 if(p == null) {
4803 dataOnly = true;
4804 PackageSetting ps = mSettings.mPackages.get(packageName);
4805 if((ps == null) || (ps.pkg == null)) {
4806 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4807 return false;
4808 }
4809 p = ps.pkg;
4810 }
4811 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004812 boolean useEncryptedFSDir = false;
4813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 if(!dataOnly) {
4815 //need to check this only for fully installed applications
4816 if (p == null) {
4817 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4818 return false;
4819 }
4820 final ApplicationInfo applicationInfo = p.applicationInfo;
4821 if (applicationInfo == null) {
4822 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4823 return false;
4824 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004825 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 }
4827 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004828 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 if (retCode < 0) {
4830 Log.w(TAG, "Couldn't remove cache files for package: "
4831 + packageName);
4832 return false;
4833 }
4834 }
4835 return true;
4836 }
4837
4838 public void deleteApplicationCacheFiles(final String packageName,
4839 final IPackageDataObserver observer) {
4840 mContext.enforceCallingOrSelfPermission(
4841 android.Manifest.permission.DELETE_CACHE_FILES, null);
4842 // Queue up an async operation since the package deletion may take a little while.
4843 mHandler.post(new Runnable() {
4844 public void run() {
4845 mHandler.removeCallbacks(this);
4846 final boolean succeded;
4847 synchronized (mInstallLock) {
4848 succeded = deleteApplicationCacheFilesLI(packageName);
4849 }
4850 if(observer != null) {
4851 try {
4852 observer.onRemoveCompleted(packageName, succeded);
4853 } catch (RemoteException e) {
4854 Log.i(TAG, "Observer no longer exists.");
4855 }
4856 } //end if observer
4857 } //end run
4858 });
4859 }
4860
4861 private boolean deleteApplicationCacheFilesLI(String packageName) {
4862 if (packageName == null) {
4863 Log.w(TAG, "Attempt to delete null packageName.");
4864 return false;
4865 }
4866 PackageParser.Package p;
4867 synchronized (mPackages) {
4868 p = mPackages.get(packageName);
4869 }
4870 if (p == null) {
4871 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4872 return false;
4873 }
4874 final ApplicationInfo applicationInfo = p.applicationInfo;
4875 if (applicationInfo == null) {
4876 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4877 return false;
4878 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004879 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004881 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 if (retCode < 0) {
4883 Log.w(TAG, "Couldn't remove cache files for package: "
4884 + packageName);
4885 return false;
4886 }
4887 }
4888 return true;
4889 }
4890
4891 public void getPackageSizeInfo(final String packageName,
4892 final IPackageStatsObserver observer) {
4893 mContext.enforceCallingOrSelfPermission(
4894 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4895 // Queue up an async operation since the package deletion may take a little while.
4896 mHandler.post(new Runnable() {
4897 public void run() {
4898 mHandler.removeCallbacks(this);
4899 PackageStats lStats = new PackageStats(packageName);
4900 final boolean succeded;
4901 synchronized (mInstallLock) {
4902 succeded = getPackageSizeInfoLI(packageName, lStats);
4903 }
4904 if(observer != null) {
4905 try {
4906 observer.onGetStatsCompleted(lStats, succeded);
4907 } catch (RemoteException e) {
4908 Log.i(TAG, "Observer no longer exists.");
4909 }
4910 } //end if observer
4911 } //end run
4912 });
4913 }
4914
4915 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4916 if (packageName == null) {
4917 Log.w(TAG, "Attempt to get size of null packageName.");
4918 return false;
4919 }
4920 PackageParser.Package p;
4921 boolean dataOnly = false;
4922 synchronized (mPackages) {
4923 p = mPackages.get(packageName);
4924 if(p == null) {
4925 dataOnly = true;
4926 PackageSetting ps = mSettings.mPackages.get(packageName);
4927 if((ps == null) || (ps.pkg == null)) {
4928 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4929 return false;
4930 }
4931 p = ps.pkg;
4932 }
4933 }
4934 String publicSrcDir = null;
4935 if(!dataOnly) {
4936 final ApplicationInfo applicationInfo = p.applicationInfo;
4937 if (applicationInfo == null) {
4938 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4939 return false;
4940 }
4941 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4942 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004943 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 if (mInstaller != null) {
4945 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08004946 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 if (res < 0) {
4948 return false;
4949 } else {
4950 return true;
4951 }
4952 }
4953 return true;
4954 }
4955
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 public void addPackageToPreferred(String packageName) {
4958 mContext.enforceCallingOrSelfPermission(
4959 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004960 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 }
4962
4963 public void removePackageFromPreferred(String packageName) {
4964 mContext.enforceCallingOrSelfPermission(
4965 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004966 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 }
4968
4969 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004970 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 }
4972
4973 public void addPreferredActivity(IntentFilter filter, int match,
4974 ComponentName[] set, ComponentName activity) {
4975 mContext.enforceCallingOrSelfPermission(
4976 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4977
4978 synchronized (mPackages) {
4979 Log.i(TAG, "Adding preferred activity " + activity + ":");
4980 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4981 mSettings.mPreferredActivities.addFilter(
4982 new PreferredActivity(filter, match, set, activity));
4983 mSettings.writeLP();
4984 }
4985 }
4986
Satish Sampath8dbe6122009-06-02 23:35:54 +01004987 public void replacePreferredActivity(IntentFilter filter, int match,
4988 ComponentName[] set, ComponentName activity) {
4989 mContext.enforceCallingOrSelfPermission(
4990 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4991 if (filter.countActions() != 1) {
4992 throw new IllegalArgumentException(
4993 "replacePreferredActivity expects filter to have only 1 action.");
4994 }
4995 if (filter.countCategories() != 1) {
4996 throw new IllegalArgumentException(
4997 "replacePreferredActivity expects filter to have only 1 category.");
4998 }
4999 if (filter.countDataAuthorities() != 0
5000 || filter.countDataPaths() != 0
5001 || filter.countDataSchemes() != 0
5002 || filter.countDataTypes() != 0) {
5003 throw new IllegalArgumentException(
5004 "replacePreferredActivity expects filter to have no data authorities, " +
5005 "paths, schemes or types.");
5006 }
5007 synchronized (mPackages) {
5008 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5009 String action = filter.getAction(0);
5010 String category = filter.getCategory(0);
5011 while (it.hasNext()) {
5012 PreferredActivity pa = it.next();
5013 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5014 it.remove();
5015 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5016 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5017 }
5018 }
5019 addPreferredActivity(filter, match, set, activity);
5020 }
5021 }
5022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 public void clearPackagePreferredActivities(String packageName) {
5024 mContext.enforceCallingOrSelfPermission(
5025 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5026
5027 synchronized (mPackages) {
5028 if (clearPackagePreferredActivitiesLP(packageName)) {
5029 mSettings.writeLP();
5030 }
5031 }
5032 }
5033
5034 boolean clearPackagePreferredActivitiesLP(String packageName) {
5035 boolean changed = false;
5036 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5037 while (it.hasNext()) {
5038 PreferredActivity pa = it.next();
5039 if (pa.mActivity.getPackageName().equals(packageName)) {
5040 it.remove();
5041 changed = true;
5042 }
5043 }
5044 return changed;
5045 }
5046
5047 public int getPreferredActivities(List<IntentFilter> outFilters,
5048 List<ComponentName> outActivities, String packageName) {
5049
5050 int num = 0;
5051 synchronized (mPackages) {
5052 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5053 while (it.hasNext()) {
5054 PreferredActivity pa = it.next();
5055 if (packageName == null
5056 || pa.mActivity.getPackageName().equals(packageName)) {
5057 if (outFilters != null) {
5058 outFilters.add(new IntentFilter(pa));
5059 }
5060 if (outActivities != null) {
5061 outActivities.add(pa.mActivity);
5062 }
5063 }
5064 }
5065 }
5066
5067 return num;
5068 }
5069
5070 public void setApplicationEnabledSetting(String appPackageName,
5071 int newState, int flags) {
5072 setEnabledSetting(appPackageName, null, newState, flags);
5073 }
5074
5075 public void setComponentEnabledSetting(ComponentName componentName,
5076 int newState, int flags) {
5077 setEnabledSetting(componentName.getPackageName(),
5078 componentName.getClassName(), newState, flags);
5079 }
5080
5081 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005082 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5084 || newState == COMPONENT_ENABLED_STATE_ENABLED
5085 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5086 throw new IllegalArgumentException("Invalid new component state: "
5087 + newState);
5088 }
5089 PackageSetting pkgSetting;
5090 final int uid = Binder.getCallingUid();
5091 final int permission = mContext.checkCallingPermission(
5092 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5093 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005094 boolean sendNow = false;
5095 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005096 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005098 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005100 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005102 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005104 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 }
5106 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005107 "Unknown component: " + packageName
5108 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 }
5110 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5111 throw new SecurityException(
5112 "Permission Denial: attempt to change component state from pid="
5113 + Binder.getCallingPid()
5114 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5115 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005116 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 // We're dealing with an application/package level state change
5118 pkgSetting.enabled = newState;
5119 } else {
5120 // We're dealing with a component level state change
5121 switch (newState) {
5122 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005123 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 break;
5125 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005126 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 break;
5128 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005129 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 break;
5131 default:
5132 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005133 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 }
5135 }
5136 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005137 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005138 components = mPendingBroadcasts.get(packageName);
5139 boolean newPackage = components == null;
5140 if (newPackage) {
5141 components = new ArrayList<String>();
5142 }
5143 if (!components.contains(componentName)) {
5144 components.add(componentName);
5145 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005146 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5147 sendNow = true;
5148 // Purge entry from pending broadcast list if another one exists already
5149 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005150 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005151 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005152 if (newPackage) {
5153 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005154 }
5155 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5156 // Schedule a message
5157 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5158 }
5159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 long callingId = Binder.clearCallingIdentity();
5163 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005164 if (sendNow) {
5165 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005166 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 } finally {
5169 Binder.restoreCallingIdentity(callingId);
5170 }
5171 }
5172
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005173 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005174 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5175 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5176 + " components=" + componentNames);
5177 Bundle extras = new Bundle(4);
5178 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5179 String nameList[] = new String[componentNames.size()];
5180 componentNames.toArray(nameList);
5181 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005182 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5183 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005184 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005185 }
5186
Jacek Surazski65e13172009-04-28 15:26:38 +02005187 public String getInstallerPackageName(String packageName) {
5188 synchronized (mPackages) {
5189 PackageSetting pkg = mSettings.mPackages.get(packageName);
5190 if (pkg == null) {
5191 throw new IllegalArgumentException("Unknown package: " + packageName);
5192 }
5193 return pkg.installerPackageName;
5194 }
5195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 public int getApplicationEnabledSetting(String appPackageName) {
5198 synchronized (mPackages) {
5199 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5200 if (pkg == null) {
5201 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5202 }
5203 return pkg.enabled;
5204 }
5205 }
5206
5207 public int getComponentEnabledSetting(ComponentName componentName) {
5208 synchronized (mPackages) {
5209 final String packageNameStr = componentName.getPackageName();
5210 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5211 if (pkg == null) {
5212 throw new IllegalArgumentException("Unknown component: " + componentName);
5213 }
5214 final String classNameStr = componentName.getClassName();
5215 return pkg.currentEnabledStateLP(classNameStr);
5216 }
5217 }
5218
5219 public void enterSafeMode() {
5220 if (!mSystemReady) {
5221 mSafeMode = true;
5222 }
5223 }
5224
5225 public void systemReady() {
5226 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005227
5228 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005229 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005230 mContext.getContentResolver(),
5231 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005232 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005233 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005234 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 }
5237
5238 public boolean isSafeMode() {
5239 return mSafeMode;
5240 }
5241
5242 public boolean hasSystemUidErrors() {
5243 return mHasSystemUidErrors;
5244 }
5245
5246 static String arrayToString(int[] array) {
5247 StringBuffer buf = new StringBuffer(128);
5248 buf.append('[');
5249 if (array != null) {
5250 for (int i=0; i<array.length; i++) {
5251 if (i > 0) buf.append(", ");
5252 buf.append(array[i]);
5253 }
5254 }
5255 buf.append(']');
5256 return buf.toString();
5257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 @Override
5260 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5261 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5262 != PackageManager.PERMISSION_GRANTED) {
5263 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5264 + Binder.getCallingPid()
5265 + ", uid=" + Binder.getCallingUid()
5266 + " without permission "
5267 + android.Manifest.permission.DUMP);
5268 return;
5269 }
5270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 synchronized (mPackages) {
5272 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005273 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 pw.println(" ");
5275 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005276 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 pw.println(" ");
5278 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005279 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 pw.println(" ");
5281 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005282 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 pw.println("Permissions:");
5285 {
5286 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005287 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5288 pw.print(Integer.toHexString(System.identityHashCode(p)));
5289 pw.println("):");
5290 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5291 pw.print(" uid="); pw.print(p.uid);
5292 pw.print(" gids="); pw.print(arrayToString(p.gids));
5293 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 }
5295 }
5296 pw.println(" ");
5297 pw.println("Packages:");
5298 {
5299 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005300 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5301 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5302 pw.println("):");
5303 pw.print(" userId="); pw.print(ps.userId);
5304 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5305 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5306 pw.print(" pkg="); pw.println(ps.pkg);
5307 pw.print(" codePath="); pw.println(ps.codePathString);
5308 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005310 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005311 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005312 pw.print(" supportsScreens=[");
5313 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005314 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005315 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005316 if (!first) pw.print(", ");
5317 first = false;
5318 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005320 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005321 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005322 if (!first) pw.print(", ");
5323 first = false;
5324 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005325 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005326 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005327 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005328 if (!first) pw.print(", ");
5329 first = false;
5330 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005332 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005333 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005334 if (!first) pw.print(", ");
5335 first = false;
5336 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005337 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005338 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005339 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5340 if (!first) pw.print(", ");
5341 first = false;
5342 pw.print("anyDensity");
5343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005345 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005346 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5347 pw.print(" signatures="); pw.println(ps.signatures);
5348 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5349 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5350 pw.print(" installStatus="); pw.print(ps.installStatus);
5351 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 if (ps.disabledComponents.size() > 0) {
5353 pw.println(" disabledComponents:");
5354 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005355 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005356 }
5357 }
5358 if (ps.enabledComponents.size() > 0) {
5359 pw.println(" enabledComponents:");
5360 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005361 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 }
5363 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005364 if (ps.grantedPermissions.size() > 0) {
5365 pw.println(" grantedPermissions:");
5366 for (String s : ps.grantedPermissions) {
5367 pw.print(" "); pw.println(s);
5368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005370 if (ps.loadedPermissions.size() > 0) {
5371 pw.println(" loadedPermissions:");
5372 for (String s : ps.loadedPermissions) {
5373 pw.print(" "); pw.println(s);
5374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 }
5376 }
5377 }
5378 pw.println(" ");
5379 pw.println("Shared Users:");
5380 {
5381 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005382 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5383 pw.print(Integer.toHexString(System.identityHashCode(su)));
5384 pw.println("):");
5385 pw.print(" userId="); pw.print(su.userId);
5386 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 pw.println(" grantedPermissions:");
5388 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005389 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 }
5391 pw.println(" loadedPermissions:");
5392 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005393 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 }
5395 }
5396 }
5397 pw.println(" ");
5398 pw.println("Settings parse messages:");
5399 pw.println(mSettings.mReadMessages.toString());
5400 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005401
5402 synchronized (mProviders) {
5403 pw.println(" ");
5404 pw.println("Registered ContentProviders:");
5405 for (PackageParser.Provider p : mProviders.values()) {
5406 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5407 pw.println(p.toString());
5408 }
5409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 }
5411
5412 static final class BasePermission {
5413 final static int TYPE_NORMAL = 0;
5414 final static int TYPE_BUILTIN = 1;
5415 final static int TYPE_DYNAMIC = 2;
5416
5417 final String name;
5418 final String sourcePackage;
5419 final int type;
5420 PackageParser.Permission perm;
5421 PermissionInfo pendingInfo;
5422 int uid;
5423 int[] gids;
5424
5425 BasePermission(String _name, String _sourcePackage, int _type) {
5426 name = _name;
5427 sourcePackage = _sourcePackage;
5428 type = _type;
5429 }
5430 }
5431
5432 static class PackageSignatures {
5433 private Signature[] mSignatures;
5434
5435 PackageSignatures(Signature[] sigs) {
5436 assignSignatures(sigs);
5437 }
5438
5439 PackageSignatures() {
5440 }
5441
5442 void writeXml(XmlSerializer serializer, String tagName,
5443 ArrayList<Signature> pastSignatures) throws IOException {
5444 if (mSignatures == null) {
5445 return;
5446 }
5447 serializer.startTag(null, tagName);
5448 serializer.attribute(null, "count",
5449 Integer.toString(mSignatures.length));
5450 for (int i=0; i<mSignatures.length; i++) {
5451 serializer.startTag(null, "cert");
5452 final Signature sig = mSignatures[i];
5453 final int sigHash = sig.hashCode();
5454 final int numPast = pastSignatures.size();
5455 int j;
5456 for (j=0; j<numPast; j++) {
5457 Signature pastSig = pastSignatures.get(j);
5458 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5459 serializer.attribute(null, "index", Integer.toString(j));
5460 break;
5461 }
5462 }
5463 if (j >= numPast) {
5464 pastSignatures.add(sig);
5465 serializer.attribute(null, "index", Integer.toString(numPast));
5466 serializer.attribute(null, "key", sig.toCharsString());
5467 }
5468 serializer.endTag(null, "cert");
5469 }
5470 serializer.endTag(null, tagName);
5471 }
5472
5473 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5474 throws IOException, XmlPullParserException {
5475 String countStr = parser.getAttributeValue(null, "count");
5476 if (countStr == null) {
5477 reportSettingsProblem(Log.WARN,
5478 "Error in package manager settings: <signatures> has"
5479 + " no count at " + parser.getPositionDescription());
5480 XmlUtils.skipCurrentTag(parser);
5481 }
5482 final int count = Integer.parseInt(countStr);
5483 mSignatures = new Signature[count];
5484 int pos = 0;
5485
5486 int outerDepth = parser.getDepth();
5487 int type;
5488 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5489 && (type != XmlPullParser.END_TAG
5490 || parser.getDepth() > outerDepth)) {
5491 if (type == XmlPullParser.END_TAG
5492 || type == XmlPullParser.TEXT) {
5493 continue;
5494 }
5495
5496 String tagName = parser.getName();
5497 if (tagName.equals("cert")) {
5498 if (pos < count) {
5499 String index = parser.getAttributeValue(null, "index");
5500 if (index != null) {
5501 try {
5502 int idx = Integer.parseInt(index);
5503 String key = parser.getAttributeValue(null, "key");
5504 if (key == null) {
5505 if (idx >= 0 && idx < pastSignatures.size()) {
5506 Signature sig = pastSignatures.get(idx);
5507 if (sig != null) {
5508 mSignatures[pos] = pastSignatures.get(idx);
5509 pos++;
5510 } else {
5511 reportSettingsProblem(Log.WARN,
5512 "Error in package manager settings: <cert> "
5513 + "index " + index + " is not defined at "
5514 + parser.getPositionDescription());
5515 }
5516 } else {
5517 reportSettingsProblem(Log.WARN,
5518 "Error in package manager settings: <cert> "
5519 + "index " + index + " is out of bounds at "
5520 + parser.getPositionDescription());
5521 }
5522 } else {
5523 while (pastSignatures.size() <= idx) {
5524 pastSignatures.add(null);
5525 }
5526 Signature sig = new Signature(key);
5527 pastSignatures.set(idx, sig);
5528 mSignatures[pos] = sig;
5529 pos++;
5530 }
5531 } catch (NumberFormatException e) {
5532 reportSettingsProblem(Log.WARN,
5533 "Error in package manager settings: <cert> "
5534 + "index " + index + " is not a number at "
5535 + parser.getPositionDescription());
5536 }
5537 } else {
5538 reportSettingsProblem(Log.WARN,
5539 "Error in package manager settings: <cert> has"
5540 + " no index at " + parser.getPositionDescription());
5541 }
5542 } else {
5543 reportSettingsProblem(Log.WARN,
5544 "Error in package manager settings: too "
5545 + "many <cert> tags, expected " + count
5546 + " at " + parser.getPositionDescription());
5547 }
5548 } else {
5549 reportSettingsProblem(Log.WARN,
5550 "Unknown element under <cert>: "
5551 + parser.getName());
5552 }
5553 XmlUtils.skipCurrentTag(parser);
5554 }
5555
5556 if (pos < count) {
5557 // Should never happen -- there is an error in the written
5558 // settings -- but if it does we don't want to generate
5559 // a bad array.
5560 Signature[] newSigs = new Signature[pos];
5561 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5562 mSignatures = newSigs;
5563 }
5564 }
5565
5566 /**
5567 * If any of the given 'sigs' is contained in the existing signatures,
5568 * then completely replace the current signatures with the ones in
5569 * 'sigs'. This is used for updating an existing package to a newly
5570 * installed version.
5571 */
5572 boolean updateSignatures(Signature[] sigs, boolean update) {
5573 if (mSignatures == null) {
5574 if (update) {
5575 assignSignatures(sigs);
5576 }
5577 return true;
5578 }
5579 if (sigs == null) {
5580 return false;
5581 }
5582
5583 for (int i=0; i<sigs.length; i++) {
5584 Signature sig = sigs[i];
5585 for (int j=0; j<mSignatures.length; j++) {
5586 if (mSignatures[j].equals(sig)) {
5587 if (update) {
5588 assignSignatures(sigs);
5589 }
5590 return true;
5591 }
5592 }
5593 }
5594 return false;
5595 }
5596
5597 /**
5598 * If any of the given 'sigs' is contained in the existing signatures,
5599 * then add in any new signatures found in 'sigs'. This is used for
5600 * including a new package into an existing shared user id.
5601 */
5602 boolean mergeSignatures(Signature[] sigs, boolean update) {
5603 if (mSignatures == null) {
5604 if (update) {
5605 assignSignatures(sigs);
5606 }
5607 return true;
5608 }
5609 if (sigs == null) {
5610 return false;
5611 }
5612
5613 Signature[] added = null;
5614 int addedCount = 0;
5615 boolean haveMatch = false;
5616 for (int i=0; i<sigs.length; i++) {
5617 Signature sig = sigs[i];
5618 boolean found = false;
5619 for (int j=0; j<mSignatures.length; j++) {
5620 if (mSignatures[j].equals(sig)) {
5621 found = true;
5622 haveMatch = true;
5623 break;
5624 }
5625 }
5626
5627 if (!found) {
5628 if (added == null) {
5629 added = new Signature[sigs.length];
5630 }
5631 added[i] = sig;
5632 addedCount++;
5633 }
5634 }
5635
5636 if (!haveMatch) {
5637 // Nothing matched -- reject the new signatures.
5638 return false;
5639 }
5640 if (added == null) {
5641 // Completely matched -- nothing else to do.
5642 return true;
5643 }
5644
5645 // Add additional signatures in.
5646 if (update) {
5647 Signature[] total = new Signature[addedCount+mSignatures.length];
5648 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5649 int j = mSignatures.length;
5650 for (int i=0; i<added.length; i++) {
5651 if (added[i] != null) {
5652 total[j] = added[i];
5653 j++;
5654 }
5655 }
5656 mSignatures = total;
5657 }
5658 return true;
5659 }
5660
5661 private void assignSignatures(Signature[] sigs) {
5662 if (sigs == null) {
5663 mSignatures = null;
5664 return;
5665 }
5666 mSignatures = new Signature[sigs.length];
5667 for (int i=0; i<sigs.length; i++) {
5668 mSignatures[i] = sigs[i];
5669 }
5670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 @Override
5673 public String toString() {
5674 StringBuffer buf = new StringBuffer(128);
5675 buf.append("PackageSignatures{");
5676 buf.append(Integer.toHexString(System.identityHashCode(this)));
5677 buf.append(" [");
5678 if (mSignatures != null) {
5679 for (int i=0; i<mSignatures.length; i++) {
5680 if (i > 0) buf.append(", ");
5681 buf.append(Integer.toHexString(
5682 System.identityHashCode(mSignatures[i])));
5683 }
5684 }
5685 buf.append("]}");
5686 return buf.toString();
5687 }
5688 }
5689
5690 static class PreferredActivity extends IntentFilter {
5691 final int mMatch;
5692 final String[] mSetPackages;
5693 final String[] mSetClasses;
5694 final String[] mSetComponents;
5695 final ComponentName mActivity;
5696 final String mShortActivity;
5697 String mParseError;
5698
5699 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5700 ComponentName activity) {
5701 super(filter);
5702 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5703 mActivity = activity;
5704 mShortActivity = activity.flattenToShortString();
5705 mParseError = null;
5706 if (set != null) {
5707 final int N = set.length;
5708 String[] myPackages = new String[N];
5709 String[] myClasses = new String[N];
5710 String[] myComponents = new String[N];
5711 for (int i=0; i<N; i++) {
5712 ComponentName cn = set[i];
5713 if (cn == null) {
5714 mSetPackages = null;
5715 mSetClasses = null;
5716 mSetComponents = null;
5717 return;
5718 }
5719 myPackages[i] = cn.getPackageName().intern();
5720 myClasses[i] = cn.getClassName().intern();
5721 myComponents[i] = cn.flattenToShortString().intern();
5722 }
5723 mSetPackages = myPackages;
5724 mSetClasses = myClasses;
5725 mSetComponents = myComponents;
5726 } else {
5727 mSetPackages = null;
5728 mSetClasses = null;
5729 mSetComponents = null;
5730 }
5731 }
5732
5733 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5734 IOException {
5735 mShortActivity = parser.getAttributeValue(null, "name");
5736 mActivity = ComponentName.unflattenFromString(mShortActivity);
5737 if (mActivity == null) {
5738 mParseError = "Bad activity name " + mShortActivity;
5739 }
5740 String matchStr = parser.getAttributeValue(null, "match");
5741 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5742 String setCountStr = parser.getAttributeValue(null, "set");
5743 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5744
5745 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5746 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5747 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5748
5749 int setPos = 0;
5750
5751 int outerDepth = parser.getDepth();
5752 int type;
5753 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5754 && (type != XmlPullParser.END_TAG
5755 || parser.getDepth() > outerDepth)) {
5756 if (type == XmlPullParser.END_TAG
5757 || type == XmlPullParser.TEXT) {
5758 continue;
5759 }
5760
5761 String tagName = parser.getName();
5762 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5763 // + parser.getDepth() + " tag=" + tagName);
5764 if (tagName.equals("set")) {
5765 String name = parser.getAttributeValue(null, "name");
5766 if (name == null) {
5767 if (mParseError == null) {
5768 mParseError = "No name in set tag in preferred activity "
5769 + mShortActivity;
5770 }
5771 } else if (setPos >= setCount) {
5772 if (mParseError == null) {
5773 mParseError = "Too many set tags in preferred activity "
5774 + mShortActivity;
5775 }
5776 } else {
5777 ComponentName cn = ComponentName.unflattenFromString(name);
5778 if (cn == null) {
5779 if (mParseError == null) {
5780 mParseError = "Bad set name " + name + " in preferred activity "
5781 + mShortActivity;
5782 }
5783 } else {
5784 myPackages[setPos] = cn.getPackageName();
5785 myClasses[setPos] = cn.getClassName();
5786 myComponents[setPos] = name;
5787 setPos++;
5788 }
5789 }
5790 XmlUtils.skipCurrentTag(parser);
5791 } else if (tagName.equals("filter")) {
5792 //Log.i(TAG, "Starting to parse filter...");
5793 readFromXml(parser);
5794 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5795 // + parser.getDepth() + " tag=" + parser.getName());
5796 } else {
5797 reportSettingsProblem(Log.WARN,
5798 "Unknown element under <preferred-activities>: "
5799 + parser.getName());
5800 XmlUtils.skipCurrentTag(parser);
5801 }
5802 }
5803
5804 if (setPos != setCount) {
5805 if (mParseError == null) {
5806 mParseError = "Not enough set tags (expected " + setCount
5807 + " but found " + setPos + ") in " + mShortActivity;
5808 }
5809 }
5810
5811 mSetPackages = myPackages;
5812 mSetClasses = myClasses;
5813 mSetComponents = myComponents;
5814 }
5815
5816 public void writeToXml(XmlSerializer serializer) throws IOException {
5817 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5818 serializer.attribute(null, "name", mShortActivity);
5819 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5820 serializer.attribute(null, "set", Integer.toString(NS));
5821 for (int s=0; s<NS; s++) {
5822 serializer.startTag(null, "set");
5823 serializer.attribute(null, "name", mSetComponents[s]);
5824 serializer.endTag(null, "set");
5825 }
5826 serializer.startTag(null, "filter");
5827 super.writeToXml(serializer);
5828 serializer.endTag(null, "filter");
5829 }
5830
5831 boolean sameSet(List<ResolveInfo> query, int priority) {
5832 if (mSetPackages == null) return false;
5833 final int NQ = query.size();
5834 final int NS = mSetPackages.length;
5835 int numMatch = 0;
5836 for (int i=0; i<NQ; i++) {
5837 ResolveInfo ri = query.get(i);
5838 if (ri.priority != priority) continue;
5839 ActivityInfo ai = ri.activityInfo;
5840 boolean good = false;
5841 for (int j=0; j<NS; j++) {
5842 if (mSetPackages[j].equals(ai.packageName)
5843 && mSetClasses[j].equals(ai.name)) {
5844 numMatch++;
5845 good = true;
5846 break;
5847 }
5848 }
5849 if (!good) return false;
5850 }
5851 return numMatch == NS;
5852 }
5853 }
5854
5855 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005856 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 HashSet<String> grantedPermissions = new HashSet<String>();
5859 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 GrantedPermissions(int pkgFlags) {
5864 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5865 }
5866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 /**
5869 * Settings base class for pending and resolved classes.
5870 */
5871 static class PackageSettingBase extends GrantedPermissions {
5872 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005873 File codePath;
5874 String codePathString;
5875 File resourcePath;
5876 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 private long timeStamp;
5878 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005879 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005880
5881 PackageSignatures signatures = new PackageSignatures();
5882
5883 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 /* Explicitly disabled components */
5886 HashSet<String> disabledComponents = new HashSet<String>(0);
5887 /* Explicitly enabled components */
5888 HashSet<String> enabledComponents = new HashSet<String>(0);
5889 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5890 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005891
Jacek Surazski65e13172009-04-28 15:26:38 +02005892 /* package name of the app that installed this package */
5893 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894
5895 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005896 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 super(pkgFlags);
5898 this.name = name;
5899 this.codePath = codePath;
5900 this.codePathString = codePath.toString();
5901 this.resourcePath = resourcePath;
5902 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005903 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 }
5905
Jacek Surazski65e13172009-04-28 15:26:38 +02005906 public void setInstallerPackageName(String packageName) {
5907 installerPackageName = packageName;
5908 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005909
Jacek Surazski65e13172009-04-28 15:26:38 +02005910 String getInstallerPackageName() {
5911 return installerPackageName;
5912 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 public void setInstallStatus(int newStatus) {
5915 installStatus = newStatus;
5916 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 public int getInstallStatus() {
5919 return installStatus;
5920 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 public void setTimeStamp(long newStamp) {
5923 if (newStamp != timeStamp) {
5924 timeStamp = newStamp;
5925 timeStampString = Long.toString(newStamp);
5926 }
5927 }
5928
5929 public void setTimeStamp(long newStamp, String newStampStr) {
5930 timeStamp = newStamp;
5931 timeStampString = newStampStr;
5932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 public long getTimeStamp() {
5935 return timeStamp;
5936 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 public String getTimeStampStr() {
5939 return timeStampString;
5940 }
5941
5942 public void copyFrom(PackageSettingBase base) {
5943 grantedPermissions = base.grantedPermissions;
5944 gids = base.gids;
5945 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 timeStamp = base.timeStamp;
5948 timeStampString = base.timeStampString;
5949 signatures = base.signatures;
5950 permissionsFixed = base.permissionsFixed;
5951 disabledComponents = base.disabledComponents;
5952 enabledComponents = base.enabledComponents;
5953 enabled = base.enabled;
5954 installStatus = base.installStatus;
5955 }
5956
5957 void enableComponentLP(String componentClassName) {
5958 disabledComponents.remove(componentClassName);
5959 enabledComponents.add(componentClassName);
5960 }
5961
5962 void disableComponentLP(String componentClassName) {
5963 enabledComponents.remove(componentClassName);
5964 disabledComponents.add(componentClassName);
5965 }
5966
5967 void restoreComponentLP(String componentClassName) {
5968 enabledComponents.remove(componentClassName);
5969 disabledComponents.remove(componentClassName);
5970 }
5971
5972 int currentEnabledStateLP(String componentName) {
5973 if (enabledComponents.contains(componentName)) {
5974 return COMPONENT_ENABLED_STATE_ENABLED;
5975 } else if (disabledComponents.contains(componentName)) {
5976 return COMPONENT_ENABLED_STATE_DISABLED;
5977 } else {
5978 return COMPONENT_ENABLED_STATE_DEFAULT;
5979 }
5980 }
5981 }
5982
5983 /**
5984 * Settings data for a particular package we know about.
5985 */
5986 static final class PackageSetting extends PackageSettingBase {
5987 int userId;
5988 PackageParser.Package pkg;
5989 SharedUserSetting sharedUser;
5990
5991 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005992 int pVersionCode, int pkgFlags) {
5993 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 @Override
5997 public String toString() {
5998 return "PackageSetting{"
5999 + Integer.toHexString(System.identityHashCode(this))
6000 + " " + name + "/" + userId + "}";
6001 }
6002 }
6003
6004 /**
6005 * Settings data for a particular shared user ID we know about.
6006 */
6007 static final class SharedUserSetting extends GrantedPermissions {
6008 final String name;
6009 int userId;
6010 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6011 final PackageSignatures signatures = new PackageSignatures();
6012
6013 SharedUserSetting(String _name, int _pkgFlags) {
6014 super(_pkgFlags);
6015 name = _name;
6016 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 @Override
6019 public String toString() {
6020 return "SharedUserSetting{"
6021 + Integer.toHexString(System.identityHashCode(this))
6022 + " " + name + "/" + userId + "}";
6023 }
6024 }
6025
6026 /**
6027 * Holds information about dynamic settings.
6028 */
6029 private static final class Settings {
6030 private final File mSettingsFilename;
6031 private final File mBackupSettingsFilename;
6032 private final HashMap<String, PackageSetting> mPackages =
6033 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006034 // List of replaced system applications
6035 final HashMap<String, PackageSetting> mDisabledSysPackages =
6036 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 // The user's preferred activities associated with particular intent
6039 // filters.
6040 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6041 new IntentResolver<PreferredActivity, PreferredActivity>() {
6042 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006043 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006045 out.print(prefix); out.print(
6046 Integer.toHexString(System.identityHashCode(filter)));
6047 out.print(' ');
6048 out.print(filter.mActivity.flattenToShortString());
6049 out.print(" match=0x");
6050 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006052 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006054 out.print(prefix); out.print(" ");
6055 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 }
6057 }
6058 }
6059 };
6060 private final HashMap<String, SharedUserSetting> mSharedUsers =
6061 new HashMap<String, SharedUserSetting>();
6062 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6063 private final SparseArray<Object> mOtherUserIds =
6064 new SparseArray<Object>();
6065
6066 // For reading/writing settings file.
6067 private final ArrayList<Signature> mPastSignatures =
6068 new ArrayList<Signature>();
6069
6070 // Mapping from permission names to info about them.
6071 final HashMap<String, BasePermission> mPermissions =
6072 new HashMap<String, BasePermission>();
6073
6074 // Mapping from permission tree names to info about them.
6075 final HashMap<String, BasePermission> mPermissionTrees =
6076 new HashMap<String, BasePermission>();
6077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 private final StringBuilder mReadMessages = new StringBuilder();
6079
6080 private static final class PendingPackage extends PackageSettingBase {
6081 final int sharedId;
6082
6083 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006084 int sharedId, int pVersionCode, int pkgFlags) {
6085 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 this.sharedId = sharedId;
6087 }
6088 }
6089 private final ArrayList<PendingPackage> mPendingPackages
6090 = new ArrayList<PendingPackage>();
6091
6092 Settings() {
6093 File dataDir = Environment.getDataDirectory();
6094 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006095 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6096 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006098 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 FileUtils.setPermissions(systemDir.toString(),
6100 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6101 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6102 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006103 FileUtils.setPermissions(systemSecureDir.toString(),
6104 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6105 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6106 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 mSettingsFilename = new File(systemDir, "packages.xml");
6108 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6109 }
6110
6111 PackageSetting getPackageLP(PackageParser.Package pkg,
6112 SharedUserSetting sharedUser, File codePath, File resourcePath,
6113 int pkgFlags, boolean create, boolean add) {
6114 final String name = pkg.packageName;
6115 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006116 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 return p;
6118 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006119
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006120 PackageSetting peekPackageLP(String name) {
6121 return mPackages.get(name);
6122 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 PackageSetting p = mPackages.get(name);
6124 if (p != null && p.codePath.getPath().equals(codePath)) {
6125 return p;
6126 }
6127 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006128 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006131 void setInstallStatus(String pkgName, int status) {
6132 PackageSetting p = mPackages.get(pkgName);
6133 if(p != null) {
6134 if(p.getInstallStatus() != status) {
6135 p.setInstallStatus(status);
6136 }
6137 }
6138 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006139
Jacek Surazski65e13172009-04-28 15:26:38 +02006140 void setInstallerPackageName(String pkgName,
6141 String installerPkgName) {
6142 PackageSetting p = mPackages.get(pkgName);
6143 if(p != null) {
6144 p.setInstallerPackageName(installerPkgName);
6145 }
6146 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006147
Jacek Surazski65e13172009-04-28 15:26:38 +02006148 String getInstallerPackageName(String pkgName) {
6149 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006150 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006151 }
6152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 int getInstallStatus(String pkgName) {
6154 PackageSetting p = mPackages.get(pkgName);
6155 if(p != null) {
6156 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 return -1;
6159 }
6160
6161 SharedUserSetting getSharedUserLP(String name,
6162 int pkgFlags, boolean create) {
6163 SharedUserSetting s = mSharedUsers.get(name);
6164 if (s == null) {
6165 if (!create) {
6166 return null;
6167 }
6168 s = new SharedUserSetting(name, pkgFlags);
6169 if (MULTIPLE_APPLICATION_UIDS) {
6170 s.userId = newUserIdLP(s);
6171 } else {
6172 s.userId = FIRST_APPLICATION_UID;
6173 }
6174 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6175 // < 0 means we couldn't assign a userid; fall out and return
6176 // s, which is currently null
6177 if (s.userId >= 0) {
6178 mSharedUsers.put(name, s);
6179 }
6180 }
6181
6182 return s;
6183 }
6184
6185 int disableSystemPackageLP(String name) {
6186 PackageSetting p = mPackages.get(name);
6187 if(p == null) {
6188 Log.w(TAG, "Package:"+name+" is not an installed package");
6189 return -1;
6190 }
6191 PackageSetting dp = mDisabledSysPackages.get(name);
6192 // always make sure the system package code and resource paths dont change
6193 if(dp == null) {
6194 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6195 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6196 }
6197 mDisabledSysPackages.put(name, p);
6198 }
6199 return removePackageLP(name);
6200 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 PackageSetting enableSystemPackageLP(String name) {
6203 PackageSetting p = mDisabledSysPackages.get(name);
6204 if(p == null) {
6205 Log.w(TAG, "Package:"+name+" is not disabled");
6206 return null;
6207 }
6208 // Reset flag in ApplicationInfo object
6209 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6210 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6211 }
6212 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006213 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214 mDisabledSysPackages.remove(name);
6215 return ret;
6216 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006219 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 PackageSetting p = mPackages.get(name);
6221 if (p != null) {
6222 if (p.userId == uid) {
6223 return p;
6224 }
6225 reportSettingsProblem(Log.ERROR,
6226 "Adding duplicate package, keeping first: " + name);
6227 return null;
6228 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006229 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 p.userId = uid;
6231 if (addUserIdLP(uid, p, name)) {
6232 mPackages.put(name, p);
6233 return p;
6234 }
6235 return null;
6236 }
6237
6238 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6239 SharedUserSetting s = mSharedUsers.get(name);
6240 if (s != null) {
6241 if (s.userId == uid) {
6242 return s;
6243 }
6244 reportSettingsProblem(Log.ERROR,
6245 "Adding duplicate shared user, keeping first: " + name);
6246 return null;
6247 }
6248 s = new SharedUserSetting(name, pkgFlags);
6249 s.userId = uid;
6250 if (addUserIdLP(uid, s, name)) {
6251 mSharedUsers.put(name, s);
6252 return s;
6253 }
6254 return null;
6255 }
6256
6257 private PackageSetting getPackageLP(String name,
6258 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006259 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 PackageSetting p = mPackages.get(name);
6261 if (p != null) {
6262 if (!p.codePath.equals(codePath)) {
6263 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006264 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006265 // This is an updated system app with versions in both system
6266 // and data partition. Just let the most recent version
6267 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006268 Log.w(TAG, "Trying to update system app code path from " +
6269 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006270 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006271 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006272 reportSettingsProblem(Log.WARN,
6273 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006274 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006276 }
6277 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 reportSettingsProblem(Log.WARN,
6279 "Package " + name + " shared user changed from "
6280 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6281 + " to "
6282 + (sharedUser != null ? sharedUser.name : "<nothing>")
6283 + "; replacing with new");
6284 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006285 } else {
6286 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6287 // If what we are scanning is a system package, then
6288 // make it so, regardless of whether it was previously
6289 // installed only in the data partition.
6290 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 }
6293 }
6294 if (p == null) {
6295 // Create a new PackageSettings entry. this can end up here because
6296 // of code path mismatch or user id mismatch of an updated system partition
6297 if (!create) {
6298 return null;
6299 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006300 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006302 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 if (sharedUser != null) {
6304 p.userId = sharedUser.userId;
6305 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006306 // Clone the setting here for disabled system packages
6307 PackageSetting dis = mDisabledSysPackages.get(name);
6308 if (dis != null) {
6309 // For disabled packages a new setting is created
6310 // from the existing user id. This still has to be
6311 // added to list of user id's
6312 // Copy signatures from previous setting
6313 if (dis.signatures.mSignatures != null) {
6314 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6315 }
6316 p.userId = dis.userId;
6317 // Clone permissions
6318 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6319 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6320 // Clone component info
6321 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6322 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6323 // Add new setting to list of user ids
6324 addUserIdLP(p.userId, p, name);
6325 } else {
6326 // Assign new user id
6327 p.userId = newUserIdLP(p);
6328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 } else {
6330 p.userId = FIRST_APPLICATION_UID;
6331 }
6332 if (p.userId < 0) {
6333 reportSettingsProblem(Log.WARN,
6334 "Package " + name + " could not be assigned a valid uid");
6335 return null;
6336 }
6337 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006338 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006340 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 }
6342 }
6343 return p;
6344 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006345
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006346 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006347 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006348 String codePath = pkg.applicationInfo.sourceDir;
6349 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006350 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006351 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006352 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006353 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006354 p.codePath = new File(codePath);
6355 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006356 }
6357 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006358 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006359 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006360 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006361 p.resourcePath = new File(resourcePath);
6362 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006363 }
6364 // Update version code if needed
6365 if (pkg.mVersionCode != p.versionCode) {
6366 p.versionCode = pkg.mVersionCode;
6367 }
6368 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6369 }
6370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 // Utility method that adds a PackageSetting to mPackages and
6372 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006373 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006374 SharedUserSetting sharedUser) {
6375 mPackages.put(name, p);
6376 if (sharedUser != null) {
6377 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6378 reportSettingsProblem(Log.ERROR,
6379 "Package " + p.name + " was user "
6380 + p.sharedUser + " but is now " + sharedUser
6381 + "; I am not changing its files so it will probably fail!");
6382 p.sharedUser.packages.remove(p);
6383 } else if (p.userId != sharedUser.userId) {
6384 reportSettingsProblem(Log.ERROR,
6385 "Package " + p.name + " was user id " + p.userId
6386 + " but is now user " + sharedUser
6387 + " with id " + sharedUser.userId
6388 + "; I am not changing its files so it will probably fail!");
6389 }
6390
6391 sharedUser.packages.add(p);
6392 p.sharedUser = sharedUser;
6393 p.userId = sharedUser.userId;
6394 }
6395 }
6396
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006397 /*
6398 * Update the shared user setting when a package using
6399 * specifying the shared user id is removed. The gids
6400 * associated with each permission of the deleted package
6401 * are removed from the shared user's gid list only if its
6402 * not in use by other permissions of packages in the
6403 * shared user setting.
6404 */
6405 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6407 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6408 return;
6409 }
6410 // No sharedUserId
6411 if (deletedPs.sharedUser == null) {
6412 return;
6413 }
6414 SharedUserSetting sus = deletedPs.sharedUser;
6415 // Update permissions
6416 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6417 boolean used = false;
6418 if (!sus.grantedPermissions.contains (eachPerm)) {
6419 continue;
6420 }
6421 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006422 if (pkg.pkg != null &&
6423 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6424 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006425 used = true;
6426 break;
6427 }
6428 }
6429 if (!used) {
6430 // can safely delete this permission from list
6431 sus.grantedPermissions.remove(eachPerm);
6432 sus.loadedPermissions.remove(eachPerm);
6433 }
6434 }
6435 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006436 int newGids[] = globalGids;
6437 for (String eachPerm : sus.grantedPermissions) {
6438 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006439 if (bp != null) {
6440 newGids = appendInts(newGids, bp.gids);
6441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 }
6443 sus.gids = newGids;
6444 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 private int removePackageLP(String name) {
6447 PackageSetting p = mPackages.get(name);
6448 if (p != null) {
6449 mPackages.remove(name);
6450 if (p.sharedUser != null) {
6451 p.sharedUser.packages.remove(p);
6452 if (p.sharedUser.packages.size() == 0) {
6453 mSharedUsers.remove(p.sharedUser.name);
6454 removeUserIdLP(p.sharedUser.userId);
6455 return p.sharedUser.userId;
6456 }
6457 } else {
6458 removeUserIdLP(p.userId);
6459 return p.userId;
6460 }
6461 }
6462 return -1;
6463 }
6464
6465 private boolean addUserIdLP(int uid, Object obj, Object name) {
6466 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6467 return false;
6468 }
6469
6470 if (uid >= FIRST_APPLICATION_UID) {
6471 int N = mUserIds.size();
6472 final int index = uid - FIRST_APPLICATION_UID;
6473 while (index >= N) {
6474 mUserIds.add(null);
6475 N++;
6476 }
6477 if (mUserIds.get(index) != null) {
6478 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006479 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 + " name=" + name);
6481 return false;
6482 }
6483 mUserIds.set(index, obj);
6484 } else {
6485 if (mOtherUserIds.get(uid) != null) {
6486 reportSettingsProblem(Log.ERROR,
6487 "Adding duplicate shared id: " + uid
6488 + " name=" + name);
6489 return false;
6490 }
6491 mOtherUserIds.put(uid, obj);
6492 }
6493 return true;
6494 }
6495
6496 public Object getUserIdLP(int uid) {
6497 if (uid >= FIRST_APPLICATION_UID) {
6498 int N = mUserIds.size();
6499 final int index = uid - FIRST_APPLICATION_UID;
6500 return index < N ? mUserIds.get(index) : null;
6501 } else {
6502 return mOtherUserIds.get(uid);
6503 }
6504 }
6505
6506 private void removeUserIdLP(int uid) {
6507 if (uid >= FIRST_APPLICATION_UID) {
6508 int N = mUserIds.size();
6509 final int index = uid - FIRST_APPLICATION_UID;
6510 if (index < N) mUserIds.set(index, null);
6511 } else {
6512 mOtherUserIds.remove(uid);
6513 }
6514 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 void writeLP() {
6517 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6518
6519 // Keep the old settings around until we know the new ones have
6520 // been successfully written.
6521 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006522 // Presence of backup settings file indicates that we failed
6523 // to persist settings earlier. So preserve the older
6524 // backup for future reference since the current settings
6525 // might have been corrupted.
6526 if (!mBackupSettingsFilename.exists()) {
6527 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6528 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6529 return;
6530 }
6531 } else {
6532 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 }
6535
6536 mPastSignatures.clear();
6537
6538 try {
6539 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6540
6541 //XmlSerializer serializer = XmlUtils.serializerInstance();
6542 XmlSerializer serializer = new FastXmlSerializer();
6543 serializer.setOutput(str, "utf-8");
6544 serializer.startDocument(null, true);
6545 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6546
6547 serializer.startTag(null, "packages");
6548
6549 serializer.startTag(null, "permission-trees");
6550 for (BasePermission bp : mPermissionTrees.values()) {
6551 writePermission(serializer, bp);
6552 }
6553 serializer.endTag(null, "permission-trees");
6554
6555 serializer.startTag(null, "permissions");
6556 for (BasePermission bp : mPermissions.values()) {
6557 writePermission(serializer, bp);
6558 }
6559 serializer.endTag(null, "permissions");
6560
6561 for (PackageSetting pkg : mPackages.values()) {
6562 writePackage(serializer, pkg);
6563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6566 writeDisabledSysPackage(serializer, pkg);
6567 }
6568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006569 serializer.startTag(null, "preferred-activities");
6570 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6571 serializer.startTag(null, "item");
6572 pa.writeToXml(serializer);
6573 serializer.endTag(null, "item");
6574 }
6575 serializer.endTag(null, "preferred-activities");
6576
6577 for (SharedUserSetting usr : mSharedUsers.values()) {
6578 serializer.startTag(null, "shared-user");
6579 serializer.attribute(null, "name", usr.name);
6580 serializer.attribute(null, "userId",
6581 Integer.toString(usr.userId));
6582 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6583 serializer.startTag(null, "perms");
6584 for (String name : usr.grantedPermissions) {
6585 serializer.startTag(null, "item");
6586 serializer.attribute(null, "name", name);
6587 serializer.endTag(null, "item");
6588 }
6589 serializer.endTag(null, "perms");
6590 serializer.endTag(null, "shared-user");
6591 }
6592
6593 serializer.endTag(null, "packages");
6594
6595 serializer.endDocument();
6596
6597 str.flush();
6598 str.close();
6599
6600 // New settings successfully written, old ones are no longer
6601 // needed.
6602 mBackupSettingsFilename.delete();
6603 FileUtils.setPermissions(mSettingsFilename.toString(),
6604 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6605 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6606 |FileUtils.S_IROTH,
6607 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006608 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609
6610 } catch(XmlPullParserException e) {
6611 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 -08006612 } catch(java.io.IOException e) {
6613 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 -08006614 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006615 // Clean up partially written file
6616 if (mSettingsFilename.exists()) {
6617 if (!mSettingsFilename.delete()) {
6618 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6619 }
6620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006621 //Debug.stopMethodTracing();
6622 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006623
6624 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 throws java.io.IOException {
6626 serializer.startTag(null, "updated-package");
6627 serializer.attribute(null, "name", pkg.name);
6628 serializer.attribute(null, "codePath", pkg.codePathString);
6629 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006630 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6632 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6633 }
6634 if (pkg.sharedUser == null) {
6635 serializer.attribute(null, "userId",
6636 Integer.toString(pkg.userId));
6637 } else {
6638 serializer.attribute(null, "sharedUserId",
6639 Integer.toString(pkg.userId));
6640 }
6641 serializer.startTag(null, "perms");
6642 if (pkg.sharedUser == null) {
6643 // If this is a shared user, the permissions will
6644 // be written there. We still need to write an
6645 // empty permissions list so permissionsFixed will
6646 // be set.
6647 for (final String name : pkg.grantedPermissions) {
6648 BasePermission bp = mPermissions.get(name);
6649 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6650 // We only need to write signature or system permissions but this wont
6651 // match the semantics of grantedPermissions. So write all permissions.
6652 serializer.startTag(null, "item");
6653 serializer.attribute(null, "name", name);
6654 serializer.endTag(null, "item");
6655 }
6656 }
6657 }
6658 serializer.endTag(null, "perms");
6659 serializer.endTag(null, "updated-package");
6660 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006661
6662 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 throws java.io.IOException {
6664 serializer.startTag(null, "package");
6665 serializer.attribute(null, "name", pkg.name);
6666 serializer.attribute(null, "codePath", pkg.codePathString);
6667 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6668 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6669 }
6670 serializer.attribute(null, "system",
6671 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6672 ? "true" : "false");
6673 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006674 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 if (pkg.sharedUser == null) {
6676 serializer.attribute(null, "userId",
6677 Integer.toString(pkg.userId));
6678 } else {
6679 serializer.attribute(null, "sharedUserId",
6680 Integer.toString(pkg.userId));
6681 }
6682 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6683 serializer.attribute(null, "enabled",
6684 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6685 ? "true" : "false");
6686 }
6687 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6688 serializer.attribute(null, "installStatus", "false");
6689 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006690 if (pkg.installerPackageName != null) {
6691 serializer.attribute(null, "installer", pkg.installerPackageName);
6692 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006693 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6694 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6695 serializer.startTag(null, "perms");
6696 if (pkg.sharedUser == null) {
6697 // If this is a shared user, the permissions will
6698 // be written there. We still need to write an
6699 // empty permissions list so permissionsFixed will
6700 // be set.
6701 for (final String name : pkg.grantedPermissions) {
6702 serializer.startTag(null, "item");
6703 serializer.attribute(null, "name", name);
6704 serializer.endTag(null, "item");
6705 }
6706 }
6707 serializer.endTag(null, "perms");
6708 }
6709 if (pkg.disabledComponents.size() > 0) {
6710 serializer.startTag(null, "disabled-components");
6711 for (final String name : pkg.disabledComponents) {
6712 serializer.startTag(null, "item");
6713 serializer.attribute(null, "name", name);
6714 serializer.endTag(null, "item");
6715 }
6716 serializer.endTag(null, "disabled-components");
6717 }
6718 if (pkg.enabledComponents.size() > 0) {
6719 serializer.startTag(null, "enabled-components");
6720 for (final String name : pkg.enabledComponents) {
6721 serializer.startTag(null, "item");
6722 serializer.attribute(null, "name", name);
6723 serializer.endTag(null, "item");
6724 }
6725 serializer.endTag(null, "enabled-components");
6726 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006728 serializer.endTag(null, "package");
6729 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006731 void writePermission(XmlSerializer serializer, BasePermission bp)
6732 throws XmlPullParserException, java.io.IOException {
6733 if (bp.type != BasePermission.TYPE_BUILTIN
6734 && bp.sourcePackage != null) {
6735 serializer.startTag(null, "item");
6736 serializer.attribute(null, "name", bp.name);
6737 serializer.attribute(null, "package", bp.sourcePackage);
6738 if (DEBUG_SETTINGS) Log.v(TAG,
6739 "Writing perm: name=" + bp.name + " type=" + bp.type);
6740 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6741 PermissionInfo pi = bp.perm != null ? bp.perm.info
6742 : bp.pendingInfo;
6743 if (pi != null) {
6744 serializer.attribute(null, "type", "dynamic");
6745 if (pi.icon != 0) {
6746 serializer.attribute(null, "icon",
6747 Integer.toString(pi.icon));
6748 }
6749 if (pi.nonLocalizedLabel != null) {
6750 serializer.attribute(null, "label",
6751 pi.nonLocalizedLabel.toString());
6752 }
6753 if (pi.protectionLevel !=
6754 PermissionInfo.PROTECTION_NORMAL) {
6755 serializer.attribute(null, "protection",
6756 Integer.toString(pi.protectionLevel));
6757 }
6758 }
6759 }
6760 serializer.endTag(null, "item");
6761 }
6762 }
6763
6764 String getReadMessagesLP() {
6765 return mReadMessages.toString();
6766 }
6767
Oscar Montemayora8529f62009-11-18 10:14:20 -08006768 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6770 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006771 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 while(its.hasNext()) {
6773 String key = its.next();
6774 PackageSetting ps = mPackages.get(key);
6775 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006776 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006777 }
6778 }
6779 return ret;
6780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 boolean readLP() {
6783 FileInputStream str = null;
6784 if (mBackupSettingsFilename.exists()) {
6785 try {
6786 str = new FileInputStream(mBackupSettingsFilename);
6787 mReadMessages.append("Reading from backup settings file\n");
6788 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006789 if (mSettingsFilename.exists()) {
6790 // If both the backup and settings file exist, we
6791 // ignore the settings since it might have been
6792 // corrupted.
6793 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6794 mSettingsFilename.delete();
6795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006796 } catch (java.io.IOException e) {
6797 // We'll try for the normal settings file.
6798 }
6799 }
6800
6801 mPastSignatures.clear();
6802
6803 try {
6804 if (str == null) {
6805 if (!mSettingsFilename.exists()) {
6806 mReadMessages.append("No settings file found\n");
6807 Log.i(TAG, "No current settings file!");
6808 return false;
6809 }
6810 str = new FileInputStream(mSettingsFilename);
6811 }
6812 XmlPullParser parser = Xml.newPullParser();
6813 parser.setInput(str, null);
6814
6815 int type;
6816 while ((type=parser.next()) != XmlPullParser.START_TAG
6817 && type != XmlPullParser.END_DOCUMENT) {
6818 ;
6819 }
6820
6821 if (type != XmlPullParser.START_TAG) {
6822 mReadMessages.append("No start tag found in settings file\n");
6823 Log.e(TAG, "No start tag found in package manager settings");
6824 return false;
6825 }
6826
6827 int outerDepth = parser.getDepth();
6828 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6829 && (type != XmlPullParser.END_TAG
6830 || parser.getDepth() > outerDepth)) {
6831 if (type == XmlPullParser.END_TAG
6832 || type == XmlPullParser.TEXT) {
6833 continue;
6834 }
6835
6836 String tagName = parser.getName();
6837 if (tagName.equals("package")) {
6838 readPackageLP(parser);
6839 } else if (tagName.equals("permissions")) {
6840 readPermissionsLP(mPermissions, parser);
6841 } else if (tagName.equals("permission-trees")) {
6842 readPermissionsLP(mPermissionTrees, parser);
6843 } else if (tagName.equals("shared-user")) {
6844 readSharedUserLP(parser);
6845 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006846 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 } else if (tagName.equals("preferred-activities")) {
6848 readPreferredActivitiesLP(parser);
6849 } else if(tagName.equals("updated-package")) {
6850 readDisabledSysPackageLP(parser);
6851 } else {
6852 Log.w(TAG, "Unknown element under <packages>: "
6853 + parser.getName());
6854 XmlUtils.skipCurrentTag(parser);
6855 }
6856 }
6857
6858 str.close();
6859
6860 } catch(XmlPullParserException e) {
6861 mReadMessages.append("Error reading: " + e.toString());
6862 Log.e(TAG, "Error reading package manager settings", e);
6863
6864 } catch(java.io.IOException e) {
6865 mReadMessages.append("Error reading: " + e.toString());
6866 Log.e(TAG, "Error reading package manager settings", e);
6867
6868 }
6869
6870 int N = mPendingPackages.size();
6871 for (int i=0; i<N; i++) {
6872 final PendingPackage pp = mPendingPackages.get(i);
6873 Object idObj = getUserIdLP(pp.sharedId);
6874 if (idObj != null && idObj instanceof SharedUserSetting) {
6875 PackageSetting p = getPackageLP(pp.name,
6876 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006877 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006878 if (p == null) {
6879 Log.w(TAG, "Unable to create application package for "
6880 + pp.name);
6881 continue;
6882 }
6883 p.copyFrom(pp);
6884 } else if (idObj != null) {
6885 String msg = "Bad package setting: package " + pp.name
6886 + " has shared uid " + pp.sharedId
6887 + " that is not a shared uid\n";
6888 mReadMessages.append(msg);
6889 Log.e(TAG, msg);
6890 } else {
6891 String msg = "Bad package setting: package " + pp.name
6892 + " has shared uid " + pp.sharedId
6893 + " that is not defined\n";
6894 mReadMessages.append(msg);
6895 Log.e(TAG, msg);
6896 }
6897 }
6898 mPendingPackages.clear();
6899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006900 mReadMessages.append("Read completed successfully: "
6901 + mPackages.size() + " packages, "
6902 + mSharedUsers.size() + " shared uids\n");
6903
6904 return true;
6905 }
6906
6907 private int readInt(XmlPullParser parser, String ns, String name,
6908 int defValue) {
6909 String v = parser.getAttributeValue(ns, name);
6910 try {
6911 if (v == null) {
6912 return defValue;
6913 }
6914 return Integer.parseInt(v);
6915 } catch (NumberFormatException e) {
6916 reportSettingsProblem(Log.WARN,
6917 "Error in package manager settings: attribute " +
6918 name + " has bad integer value " + v + " at "
6919 + parser.getPositionDescription());
6920 }
6921 return defValue;
6922 }
6923
6924 private void readPermissionsLP(HashMap<String, BasePermission> out,
6925 XmlPullParser parser)
6926 throws IOException, XmlPullParserException {
6927 int outerDepth = parser.getDepth();
6928 int type;
6929 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6930 && (type != XmlPullParser.END_TAG
6931 || parser.getDepth() > outerDepth)) {
6932 if (type == XmlPullParser.END_TAG
6933 || type == XmlPullParser.TEXT) {
6934 continue;
6935 }
6936
6937 String tagName = parser.getName();
6938 if (tagName.equals("item")) {
6939 String name = parser.getAttributeValue(null, "name");
6940 String sourcePackage = parser.getAttributeValue(null, "package");
6941 String ptype = parser.getAttributeValue(null, "type");
6942 if (name != null && sourcePackage != null) {
6943 boolean dynamic = "dynamic".equals(ptype);
6944 BasePermission bp = new BasePermission(name, sourcePackage,
6945 dynamic
6946 ? BasePermission.TYPE_DYNAMIC
6947 : BasePermission.TYPE_NORMAL);
6948 if (dynamic) {
6949 PermissionInfo pi = new PermissionInfo();
6950 pi.packageName = sourcePackage.intern();
6951 pi.name = name.intern();
6952 pi.icon = readInt(parser, null, "icon", 0);
6953 pi.nonLocalizedLabel = parser.getAttributeValue(
6954 null, "label");
6955 pi.protectionLevel = readInt(parser, null, "protection",
6956 PermissionInfo.PROTECTION_NORMAL);
6957 bp.pendingInfo = pi;
6958 }
6959 out.put(bp.name, bp);
6960 } else {
6961 reportSettingsProblem(Log.WARN,
6962 "Error in package manager settings: permissions has"
6963 + " no name at " + parser.getPositionDescription());
6964 }
6965 } else {
6966 reportSettingsProblem(Log.WARN,
6967 "Unknown element reading permissions: "
6968 + parser.getName() + " at "
6969 + parser.getPositionDescription());
6970 }
6971 XmlUtils.skipCurrentTag(parser);
6972 }
6973 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006975 private void readDisabledSysPackageLP(XmlPullParser parser)
6976 throws XmlPullParserException, IOException {
6977 String name = parser.getAttributeValue(null, "name");
6978 String codePathStr = parser.getAttributeValue(null, "codePath");
6979 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6980 if(resourcePathStr == null) {
6981 resourcePathStr = codePathStr;
6982 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006983 String version = parser.getAttributeValue(null, "version");
6984 int versionCode = 0;
6985 if (version != null) {
6986 try {
6987 versionCode = Integer.parseInt(version);
6988 } catch (NumberFormatException e) {
6989 }
6990 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006992 int pkgFlags = 0;
6993 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006994 PackageSetting ps = new PackageSetting(name,
6995 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006996 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006997 String timeStampStr = parser.getAttributeValue(null, "ts");
6998 if (timeStampStr != null) {
6999 try {
7000 long timeStamp = Long.parseLong(timeStampStr);
7001 ps.setTimeStamp(timeStamp, timeStampStr);
7002 } catch (NumberFormatException e) {
7003 }
7004 }
7005 String idStr = parser.getAttributeValue(null, "userId");
7006 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7007 if(ps.userId <= 0) {
7008 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7009 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7010 }
7011 int outerDepth = parser.getDepth();
7012 int type;
7013 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7014 && (type != XmlPullParser.END_TAG
7015 || parser.getDepth() > outerDepth)) {
7016 if (type == XmlPullParser.END_TAG
7017 || type == XmlPullParser.TEXT) {
7018 continue;
7019 }
7020
7021 String tagName = parser.getName();
7022 if (tagName.equals("perms")) {
7023 readGrantedPermissionsLP(parser,
7024 ps.grantedPermissions);
7025 } else {
7026 reportSettingsProblem(Log.WARN,
7027 "Unknown element under <updated-package>: "
7028 + parser.getName());
7029 XmlUtils.skipCurrentTag(parser);
7030 }
7031 }
7032 mDisabledSysPackages.put(name, ps);
7033 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007035 private void readPackageLP(XmlPullParser parser)
7036 throws XmlPullParserException, IOException {
7037 String name = null;
7038 String idStr = null;
7039 String sharedIdStr = null;
7040 String codePathStr = null;
7041 String resourcePathStr = null;
7042 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007043 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007044 int pkgFlags = 0;
7045 String timeStampStr;
7046 long timeStamp = 0;
7047 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007048 String version = null;
7049 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007050 try {
7051 name = parser.getAttributeValue(null, "name");
7052 idStr = parser.getAttributeValue(null, "userId");
7053 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7054 codePathStr = parser.getAttributeValue(null, "codePath");
7055 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007056 version = parser.getAttributeValue(null, "version");
7057 if (version != null) {
7058 try {
7059 versionCode = Integer.parseInt(version);
7060 } catch (NumberFormatException e) {
7061 }
7062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007064 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 if (systemStr != null) {
7066 if ("true".equals(systemStr)) {
7067 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7068 }
7069 } else {
7070 // Old settings that don't specify system... just treat
7071 // them as system, good enough.
7072 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7073 }
7074 timeStampStr = parser.getAttributeValue(null, "ts");
7075 if (timeStampStr != null) {
7076 try {
7077 timeStamp = Long.parseLong(timeStampStr);
7078 } catch (NumberFormatException e) {
7079 }
7080 }
7081 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7082 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7083 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7084 if (resourcePathStr == null) {
7085 resourcePathStr = codePathStr;
7086 }
7087 if (name == null) {
7088 reportSettingsProblem(Log.WARN,
7089 "Error in package manager settings: <package> has no name at "
7090 + parser.getPositionDescription());
7091 } else if (codePathStr == null) {
7092 reportSettingsProblem(Log.WARN,
7093 "Error in package manager settings: <package> has no codePath at "
7094 + parser.getPositionDescription());
7095 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007096 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007097 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007098 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7099 + ": userId=" + userId + " pkg=" + packageSetting);
7100 if (packageSetting == null) {
7101 reportSettingsProblem(Log.ERROR,
7102 "Failure adding uid " + userId
7103 + " while parsing settings at "
7104 + parser.getPositionDescription());
7105 } else {
7106 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7107 }
7108 } else if (sharedIdStr != null) {
7109 userId = sharedIdStr != null
7110 ? Integer.parseInt(sharedIdStr) : 0;
7111 if (userId > 0) {
7112 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007113 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7115 mPendingPackages.add((PendingPackage) packageSetting);
7116 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7117 + ": sharedUserId=" + userId + " pkg="
7118 + packageSetting);
7119 } else {
7120 reportSettingsProblem(Log.WARN,
7121 "Error in package manager settings: package "
7122 + name + " has bad sharedId " + sharedIdStr
7123 + " at " + parser.getPositionDescription());
7124 }
7125 } else {
7126 reportSettingsProblem(Log.WARN,
7127 "Error in package manager settings: package "
7128 + name + " has bad userId " + idStr + " at "
7129 + parser.getPositionDescription());
7130 }
7131 } catch (NumberFormatException e) {
7132 reportSettingsProblem(Log.WARN,
7133 "Error in package manager settings: package "
7134 + name + " has bad userId " + idStr + " at "
7135 + parser.getPositionDescription());
7136 }
7137 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007138 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 final String enabledStr = parser.getAttributeValue(null, "enabled");
7140 if (enabledStr != null) {
7141 if (enabledStr.equalsIgnoreCase("true")) {
7142 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7143 } else if (enabledStr.equalsIgnoreCase("false")) {
7144 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7145 } else if (enabledStr.equalsIgnoreCase("default")) {
7146 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7147 } else {
7148 reportSettingsProblem(Log.WARN,
7149 "Error in package manager settings: package "
7150 + name + " has bad enabled value: " + idStr
7151 + " at " + parser.getPositionDescription());
7152 }
7153 } else {
7154 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7155 }
7156 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7157 if (installStatusStr != null) {
7158 if (installStatusStr.equalsIgnoreCase("false")) {
7159 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7160 } else {
7161 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7162 }
7163 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007165 int outerDepth = parser.getDepth();
7166 int type;
7167 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7168 && (type != XmlPullParser.END_TAG
7169 || parser.getDepth() > outerDepth)) {
7170 if (type == XmlPullParser.END_TAG
7171 || type == XmlPullParser.TEXT) {
7172 continue;
7173 }
7174
7175 String tagName = parser.getName();
7176 if (tagName.equals("disabled-components")) {
7177 readDisabledComponentsLP(packageSetting, parser);
7178 } else if (tagName.equals("enabled-components")) {
7179 readEnabledComponentsLP(packageSetting, parser);
7180 } else if (tagName.equals("sigs")) {
7181 packageSetting.signatures.readXml(parser, mPastSignatures);
7182 } else if (tagName.equals("perms")) {
7183 readGrantedPermissionsLP(parser,
7184 packageSetting.loadedPermissions);
7185 packageSetting.permissionsFixed = true;
7186 } else {
7187 reportSettingsProblem(Log.WARN,
7188 "Unknown element under <package>: "
7189 + parser.getName());
7190 XmlUtils.skipCurrentTag(parser);
7191 }
7192 }
7193 } else {
7194 XmlUtils.skipCurrentTag(parser);
7195 }
7196 }
7197
7198 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7199 XmlPullParser parser)
7200 throws IOException, XmlPullParserException {
7201 int outerDepth = parser.getDepth();
7202 int type;
7203 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7204 && (type != XmlPullParser.END_TAG
7205 || parser.getDepth() > outerDepth)) {
7206 if (type == XmlPullParser.END_TAG
7207 || type == XmlPullParser.TEXT) {
7208 continue;
7209 }
7210
7211 String tagName = parser.getName();
7212 if (tagName.equals("item")) {
7213 String name = parser.getAttributeValue(null, "name");
7214 if (name != null) {
7215 packageSetting.disabledComponents.add(name.intern());
7216 } else {
7217 reportSettingsProblem(Log.WARN,
7218 "Error in package manager settings: <disabled-components> has"
7219 + " no name at " + parser.getPositionDescription());
7220 }
7221 } else {
7222 reportSettingsProblem(Log.WARN,
7223 "Unknown element under <disabled-components>: "
7224 + parser.getName());
7225 }
7226 XmlUtils.skipCurrentTag(parser);
7227 }
7228 }
7229
7230 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7231 XmlPullParser parser)
7232 throws IOException, XmlPullParserException {
7233 int outerDepth = parser.getDepth();
7234 int type;
7235 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7236 && (type != XmlPullParser.END_TAG
7237 || parser.getDepth() > outerDepth)) {
7238 if (type == XmlPullParser.END_TAG
7239 || type == XmlPullParser.TEXT) {
7240 continue;
7241 }
7242
7243 String tagName = parser.getName();
7244 if (tagName.equals("item")) {
7245 String name = parser.getAttributeValue(null, "name");
7246 if (name != null) {
7247 packageSetting.enabledComponents.add(name.intern());
7248 } else {
7249 reportSettingsProblem(Log.WARN,
7250 "Error in package manager settings: <enabled-components> has"
7251 + " no name at " + parser.getPositionDescription());
7252 }
7253 } else {
7254 reportSettingsProblem(Log.WARN,
7255 "Unknown element under <enabled-components>: "
7256 + parser.getName());
7257 }
7258 XmlUtils.skipCurrentTag(parser);
7259 }
7260 }
7261
7262 private void readSharedUserLP(XmlPullParser parser)
7263 throws XmlPullParserException, IOException {
7264 String name = null;
7265 String idStr = null;
7266 int pkgFlags = 0;
7267 SharedUserSetting su = null;
7268 try {
7269 name = parser.getAttributeValue(null, "name");
7270 idStr = parser.getAttributeValue(null, "userId");
7271 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7272 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7273 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7274 }
7275 if (name == null) {
7276 reportSettingsProblem(Log.WARN,
7277 "Error in package manager settings: <shared-user> has no name at "
7278 + parser.getPositionDescription());
7279 } else if (userId == 0) {
7280 reportSettingsProblem(Log.WARN,
7281 "Error in package manager settings: shared-user "
7282 + name + " has bad userId " + idStr + " at "
7283 + parser.getPositionDescription());
7284 } else {
7285 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7286 reportSettingsProblem(Log.ERROR,
7287 "Occurred while parsing settings at "
7288 + parser.getPositionDescription());
7289 }
7290 }
7291 } catch (NumberFormatException e) {
7292 reportSettingsProblem(Log.WARN,
7293 "Error in package manager settings: package "
7294 + name + " has bad userId " + idStr + " at "
7295 + parser.getPositionDescription());
7296 };
7297
7298 if (su != null) {
7299 int outerDepth = parser.getDepth();
7300 int type;
7301 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7302 && (type != XmlPullParser.END_TAG
7303 || parser.getDepth() > outerDepth)) {
7304 if (type == XmlPullParser.END_TAG
7305 || type == XmlPullParser.TEXT) {
7306 continue;
7307 }
7308
7309 String tagName = parser.getName();
7310 if (tagName.equals("sigs")) {
7311 su.signatures.readXml(parser, mPastSignatures);
7312 } else if (tagName.equals("perms")) {
7313 readGrantedPermissionsLP(parser, su.loadedPermissions);
7314 } else {
7315 reportSettingsProblem(Log.WARN,
7316 "Unknown element under <shared-user>: "
7317 + parser.getName());
7318 XmlUtils.skipCurrentTag(parser);
7319 }
7320 }
7321
7322 } else {
7323 XmlUtils.skipCurrentTag(parser);
7324 }
7325 }
7326
7327 private void readGrantedPermissionsLP(XmlPullParser parser,
7328 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7329 int outerDepth = parser.getDepth();
7330 int type;
7331 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7332 && (type != XmlPullParser.END_TAG
7333 || parser.getDepth() > outerDepth)) {
7334 if (type == XmlPullParser.END_TAG
7335 || type == XmlPullParser.TEXT) {
7336 continue;
7337 }
7338
7339 String tagName = parser.getName();
7340 if (tagName.equals("item")) {
7341 String name = parser.getAttributeValue(null, "name");
7342 if (name != null) {
7343 outPerms.add(name.intern());
7344 } else {
7345 reportSettingsProblem(Log.WARN,
7346 "Error in package manager settings: <perms> has"
7347 + " no name at " + parser.getPositionDescription());
7348 }
7349 } else {
7350 reportSettingsProblem(Log.WARN,
7351 "Unknown element under <perms>: "
7352 + parser.getName());
7353 }
7354 XmlUtils.skipCurrentTag(parser);
7355 }
7356 }
7357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007358 private void readPreferredActivitiesLP(XmlPullParser parser)
7359 throws XmlPullParserException, IOException {
7360 int outerDepth = parser.getDepth();
7361 int type;
7362 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7363 && (type != XmlPullParser.END_TAG
7364 || parser.getDepth() > outerDepth)) {
7365 if (type == XmlPullParser.END_TAG
7366 || type == XmlPullParser.TEXT) {
7367 continue;
7368 }
7369
7370 String tagName = parser.getName();
7371 if (tagName.equals("item")) {
7372 PreferredActivity pa = new PreferredActivity(parser);
7373 if (pa.mParseError == null) {
7374 mPreferredActivities.addFilter(pa);
7375 } else {
7376 reportSettingsProblem(Log.WARN,
7377 "Error in package manager settings: <preferred-activity> "
7378 + pa.mParseError + " at "
7379 + parser.getPositionDescription());
7380 }
7381 } else {
7382 reportSettingsProblem(Log.WARN,
7383 "Unknown element under <preferred-activities>: "
7384 + parser.getName());
7385 XmlUtils.skipCurrentTag(parser);
7386 }
7387 }
7388 }
7389
7390 // Returns -1 if we could not find an available UserId to assign
7391 private int newUserIdLP(Object obj) {
7392 // Let's be stupidly inefficient for now...
7393 final int N = mUserIds.size();
7394 for (int i=0; i<N; i++) {
7395 if (mUserIds.get(i) == null) {
7396 mUserIds.set(i, obj);
7397 return FIRST_APPLICATION_UID + i;
7398 }
7399 }
7400
7401 // None left?
7402 if (N >= MAX_APPLICATION_UIDS) {
7403 return -1;
7404 }
7405
7406 mUserIds.add(obj);
7407 return FIRST_APPLICATION_UID + N;
7408 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 public PackageSetting getDisabledSystemPkg(String name) {
7411 synchronized(mPackages) {
7412 PackageSetting ps = mDisabledSysPackages.get(name);
7413 return ps;
7414 }
7415 }
7416
7417 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7418 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7419 if (Config.LOGV) {
7420 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7421 + " componentName = " + componentInfo.name);
7422 Log.v(TAG, "enabledComponents: "
7423 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7424 Log.v(TAG, "disabledComponents: "
7425 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7426 }
7427 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7428 || ((componentInfo.enabled
7429 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7430 || (componentInfo.applicationInfo.enabled
7431 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7432 && !packageSettings.disabledComponents.contains(componentInfo.name))
7433 || packageSettings.enabledComponents.contains(componentInfo.name));
7434 }
7435 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007436
7437 // ------- apps on sdcard specific code -------
7438 static final boolean DEBUG_SD_INSTALL = false;
7439 final private String mSdEncryptKey = "none";
7440
7441 private MountService getMountService() {
7442 return (MountService) ServiceManager.getService("mount");
7443 }
7444
7445 private String createSdDir(File tmpPackageFile, String pkgName) {
7446 // Create mount point via MountService
7447 MountService mountService = getMountService();
7448 long len = tmpPackageFile.length();
7449 int mbLen = (int) (len/(1024*1024));
7450 if ((len - (mbLen * 1024 * 1024)) > 0) {
7451 mbLen++;
7452 }
7453 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
7454 String cachePath = null;
7455 // Remove any pending destroy messages
7456 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
7457 try {
7458 cachePath = mountService.createSecureContainer(pkgName,
7459 mbLen,
7460 "vfat", mSdEncryptKey, Process.SYSTEM_UID);
7461 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
7462 return cachePath;
7463 } catch(IllegalStateException e) {
7464 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7465 }
7466 // TODO just fail here and let the user delete later on.
7467 try {
7468 mountService.destroySecureContainer(pkgName);
7469 if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
7470 } catch(IllegalStateException e) {
7471 Log.e(TAG, "Failed to destroy existing cache: " + e);
7472 return null;
7473 }
7474 try {
7475 cachePath = mountService.createSecureContainer(pkgName,
7476 mbLen,
7477 "vfat", mSdEncryptKey, Process.SYSTEM_UID);
7478 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
7479 return cachePath;
7480 } catch(IllegalStateException e) {
7481 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7482 return null;
7483 }
7484 }
7485
7486 private String mountSdDir(String pkgName, int ownerUid) {
7487 try {
7488 return getMountService().mountSecureContainer(pkgName, mSdEncryptKey, ownerUid);
7489 } catch (IllegalStateException e) {
7490 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
7491 }
7492 return null;
7493 }
7494
7495 private String getSdDir(String pkgName) {
7496 String cachePath = null;
7497 try {
7498 cachePath = getMountService().getSecureContainerPath(pkgName);
7499 } catch (IllegalStateException e) {
7500 Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
7501 }
7502 return cachePath;
7503 }
7504
7505 private boolean finalizeSdDir(String pkgName) {
7506 try {
7507 getMountService().finalizeSecureContainer(pkgName);
7508 return true;
7509 } catch (IllegalStateException e) {
7510 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7511 return false;
7512 }
7513 }
7514
7515 private boolean destroySdDir(String pkgName) {
7516 try {
7517 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7518 // Don't have to send message again
7519 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
7520 }
7521 // We need to destroy right away
7522 getMountService().destroySecureContainer(pkgName);
7523 return true;
7524 } catch (IllegalStateException e) {
7525 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7526 return false;
7527 }
7528 }
7529
7530 private void sendDelayedDestroySdDir(String pkgName) {
7531 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7532 // Don't have to send message again
7533 return;
7534 }
7535 Message msg = mHandler.obtainMessage(DESTROY_SD_CONTAINER, pkgName);
7536 mHandler.sendMessageDelayed(msg, DESTROY_SD_CONTAINER_DELAY);
7537 }
7538
7539 public void updateExternalMediaStatus(boolean mediaStatus) {
7540 // TODO
7541 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542}