blob: 13079728d5043f5cc60fc835fc2fc2a48d6f277f [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;
Oscar Montemayord02546b2010-01-14 16:38:40 -080078import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.util.*;
80import android.view.Display;
81import android.view.WindowManager;
82
83import java.io.File;
84import java.io.FileDescriptor;
85import java.io.FileInputStream;
86import java.io.FileNotFoundException;
87import java.io.FileOutputStream;
88import java.io.FileReader;
89import java.io.FilenameFilter;
90import java.io.IOException;
91import java.io.InputStream;
92import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -080093import java.security.NoSuchAlgorithmException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import java.util.ArrayList;
95import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -070096import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import java.util.Collections;
98import java.util.Comparator;
99import java.util.Enumeration;
100import java.util.HashMap;
101import java.util.HashSet;
102import java.util.Iterator;
103import java.util.List;
104import java.util.Map;
105import java.util.Set;
106import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800107import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.util.zip.ZipFile;
109import java.util.zip.ZipOutputStream;
110
111class PackageManagerService extends IPackageManager.Stub {
112 private static final String TAG = "PackageManager";
113 private static final boolean DEBUG_SETTINGS = false;
114 private static final boolean DEBUG_PREFERRED = false;
115
116 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
117 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400118 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 private static final int FIRST_APPLICATION_UID =
120 Process.FIRST_APPLICATION_UID;
121 private static final int MAX_APPLICATION_UIDS = 1000;
122
123 private static final boolean SHOW_INFO = false;
124
125 private static final boolean GET_CERTIFICATES = true;
126
Oscar Montemayora8529f62009-11-18 10:14:20 -0800127 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final int REMOVE_EVENTS =
130 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
131 private static final int ADD_EVENTS =
132 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
133
134 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
135
136 static final int SCAN_MONITOR = 1<<0;
137 static final int SCAN_NO_DEX = 1<<1;
138 static final int SCAN_FORCE_DEX = 1<<2;
139 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800140 static final int SCAN_NEW_INSTALL = 1<<4;
141 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
143 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
144 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700145 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Dianne Hackborn851a5412009-05-08 12:06:44 -0700147 final int mSdkVersion = Build.VERSION.SDK_INT;
148 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
149 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 final Context mContext;
152 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700153 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 final DisplayMetrics mMetrics;
155 final int mDefParseFlags;
156 final String[] mSeparateProcesses;
157
158 // This is where all application persistent data goes.
159 final File mAppDataDir;
160
Oscar Montemayora8529f62009-11-18 10:14:20 -0800161 // If Encrypted File System feature is enabled, all application persistent data
162 // should go here instead.
163 final File mSecureAppDataDir;
164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 // This is the object monitoring the framework dir.
166 final FileObserver mFrameworkInstallObserver;
167
168 // This is the object monitoring the system app dir.
169 final FileObserver mSystemInstallObserver;
170
171 // This is the object monitoring mAppInstallDir.
172 final FileObserver mAppInstallObserver;
173
174 // This is the object monitoring mDrmAppPrivateInstallDir.
175 final FileObserver mDrmAppInstallObserver;
176
177 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
178 // LOCK HELD. Can be called with mInstallLock held.
179 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 final File mFrameworkDir;
182 final File mSystemAppDir;
183 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700184 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
186 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
187 // apps.
188 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 // Lock for state used when installing and doing other long running
193 // operations. Methods that must be called with this lock held have
194 // the prefix "LI".
195 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 // These are the directories in the 3rd party applications installed dir
198 // that we have currently loaded packages from. Keys are the application's
199 // installed zip file (absolute codePath), and values are Package.
200 final HashMap<String, PackageParser.Package> mAppDirs =
201 new HashMap<String, PackageParser.Package>();
202
203 // Information for the parser to write more useful error messages.
204 File mScanningPath;
205 int mLastScanError;
206
207 final int[] mOutPermissions = new int[3];
208
209 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 // Keys are String (package name), values are Package. This also serves
212 // as the lock for the global state. Methods that must be called with
213 // this lock held have the prefix "LP".
214 final HashMap<String, PackageParser.Package> mPackages =
215 new HashMap<String, PackageParser.Package>();
216
217 final Settings mSettings;
218 boolean mRestoredSettings;
219 boolean mReportedUidError;
220
221 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
222 int[] mGlobalGids;
223
224 // These are the built-in uid -> permission mappings that were read from the
225 // etc/permissions.xml file.
226 final SparseArray<HashSet<String>> mSystemPermissions =
227 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 // These are the built-in shared libraries that were read from the
230 // etc/permissions.xml file.
231 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800232
Dianne Hackborn49237342009-08-27 20:08:01 -0700233 // Temporary for building the final shared libraries for an .apk.
234 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800235
Dianne Hackborn49237342009-08-27 20:08:01 -0700236 // These are the features this devices supports that were read from the
237 // etc/permissions.xml file.
238 final HashMap<String, FeatureInfo> mAvailableFeatures =
239 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 // All available activities, for your resolving pleasure.
242 final ActivityIntentResolver mActivities =
243 new ActivityIntentResolver();
244
245 // All available receivers, for your resolving pleasure.
246 final ActivityIntentResolver mReceivers =
247 new ActivityIntentResolver();
248
249 // All available services, for your resolving pleasure.
250 final ServiceIntentResolver mServices = new ServiceIntentResolver();
251
252 // Keys are String (provider class name), values are Provider.
253 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
254 new HashMap<ComponentName, PackageParser.Provider>();
255
256 // Mapping from provider base names (first directory in content URI codePath)
257 // to the provider information.
258 final HashMap<String, PackageParser.Provider> mProviders =
259 new HashMap<String, PackageParser.Provider>();
260
261 // Mapping from instrumentation class names to info about them.
262 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
263 new HashMap<ComponentName, PackageParser.Instrumentation>();
264
265 // Mapping from permission names to info about them.
266 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
267 new HashMap<String, PackageParser.PermissionGroup>();
268
Dianne Hackborn854060af2009-07-09 18:14:31 -0700269 // Broadcast actions that are only available to the system.
270 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 boolean mSystemReady;
273 boolean mSafeMode;
274 boolean mHasSystemUidErrors;
275
276 ApplicationInfo mAndroidApplication;
277 final ActivityInfo mResolveActivity = new ActivityInfo();
278 final ResolveInfo mResolveInfo = new ResolveInfo();
279 ComponentName mResolveComponentName;
280 PackageParser.Package mPlatformPackage;
281
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700282 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800283 final HashMap<String, ArrayList<String>> mPendingBroadcasts
284 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700285 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800286 static final int DESTROY_SD_CONTAINER = 2;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700287 // Delay time in millisecs
288 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800289 static final int DESTROY_SD_CONTAINER_DELAY = 30 * 1000;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700290
291 class PackageHandler extends Handler {
292 PackageHandler(Looper looper) {
293 super(looper);
294 }
295 public void handleMessage(Message msg) {
296 switch (msg.what) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800297 case DESTROY_SD_CONTAINER:
298 String pkgName = (String) msg.obj;
299 if (pkgName != null) {
300 // Too bad we cannot handle the errors from destroying the containers.
301 if (!destroySdDir(pkgName)) {
302 Log.e(TAG, "Failed to destroy container for pkg : " + pkgName);
303 }
304 }
305 break;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700306 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800307 String packages[];
308 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700309 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700310 int uids[];
311 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800312 if (mPendingBroadcasts == null) {
313 return;
314 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700315 size = mPendingBroadcasts.size();
316 if (size <= 0) {
317 // Nothing to be done. Just return
318 return;
319 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800320 packages = new String[size];
321 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700322 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800323 Iterator<HashMap.Entry<String, ArrayList<String>>>
324 it = mPendingBroadcasts.entrySet().iterator();
325 int i = 0;
326 while (it.hasNext() && i < size) {
327 HashMap.Entry<String, ArrayList<String>> ent = it.next();
328 packages[i] = ent.getKey();
329 components[i] = ent.getValue();
330 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700331 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800332 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700333 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800334 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700335 mPendingBroadcasts.clear();
336 }
337 // Send broadcasts
338 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800339 sendPackageChangedBroadcast(packages[i], true,
340 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700341 }
342 break;
343 }
344 }
345 }
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 public static final IPackageManager main(Context context, boolean factoryTest) {
348 PackageManagerService m = new PackageManagerService(context, factoryTest);
349 ServiceManager.addService("package", m);
350 return m;
351 }
352
353 static String[] splitString(String str, char sep) {
354 int count = 1;
355 int i = 0;
356 while ((i=str.indexOf(sep, i)) >= 0) {
357 count++;
358 i++;
359 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 String[] res = new String[count];
362 i=0;
363 count = 0;
364 int lastI=0;
365 while ((i=str.indexOf(sep, i)) >= 0) {
366 res[count] = str.substring(lastI, i);
367 count++;
368 i++;
369 lastI = i;
370 }
371 res[count] = str.substring(lastI, str.length());
372 return res;
373 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800376 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 if (mSdkVersion <= 0) {
380 Log.w(TAG, "**** ro.build.version.sdk not set!");
381 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 mContext = context;
384 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700385 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 mMetrics = new DisplayMetrics();
387 mSettings = new Settings();
388 mSettings.addSharedUserLP("android.uid.system",
389 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
390 mSettings.addSharedUserLP("android.uid.phone",
391 MULTIPLE_APPLICATION_UIDS
392 ? RADIO_UID : FIRST_APPLICATION_UID,
393 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400394 mSettings.addSharedUserLP("android.uid.log",
395 MULTIPLE_APPLICATION_UIDS
396 ? LOG_UID : FIRST_APPLICATION_UID,
397 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398
399 String separateProcesses = SystemProperties.get("debug.separate_processes");
400 if (separateProcesses != null && separateProcesses.length() > 0) {
401 if ("*".equals(separateProcesses)) {
402 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
403 mSeparateProcesses = null;
404 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
405 } else {
406 mDefParseFlags = 0;
407 mSeparateProcesses = separateProcesses.split(",");
408 Log.w(TAG, "Running with debug.separate_processes: "
409 + separateProcesses);
410 }
411 } else {
412 mDefParseFlags = 0;
413 mSeparateProcesses = null;
414 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 Installer installer = new Installer();
417 // Little hacky thing to check if installd is here, to determine
418 // whether we are running on the simulator and thus need to take
419 // care of building the /data file structure ourself.
420 // (apparently the sim now has a working installer)
421 if (installer.ping() && Process.supportsProcesses()) {
422 mInstaller = installer;
423 } else {
424 mInstaller = null;
425 }
426
427 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
428 Display d = wm.getDefaultDisplay();
429 d.getMetrics(mMetrics);
430
431 synchronized (mInstallLock) {
432 synchronized (mPackages) {
433 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700434 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 File dataDir = Environment.getDataDirectory();
437 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800438 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
440
441 if (mInstaller == null) {
442 // Make sure these dirs exist, when we are running in
443 // the simulator.
444 // Make a wide-open directory for random misc stuff.
445 File miscDir = new File(dataDir, "misc");
446 miscDir.mkdirs();
447 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800448 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 mDrmAppPrivateInstallDir.mkdirs();
450 }
451
452 readPermissions();
453
454 mRestoredSettings = mSettings.readLP();
455 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800456
457 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800459
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800460 // Set flag to monitor and not change apk file paths when
461 // scanning install directories.
462 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700463 if (mNoDexOpt) {
464 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800465 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700471 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700474 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 /**
477 * Out of paranoia, ensure that everything in the boot class
478 * path has been dexed.
479 */
480 String bootClassPath = System.getProperty("java.boot.class.path");
481 if (bootClassPath != null) {
482 String[] paths = splitString(bootClassPath, ':');
483 for (int i=0; i<paths.length; i++) {
484 try {
485 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
486 libFiles.add(paths[i]);
487 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700488 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 }
490 } catch (FileNotFoundException e) {
491 Log.w(TAG, "Boot class path not found: " + paths[i]);
492 } catch (IOException e) {
493 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
494 }
495 }
496 } else {
497 Log.w(TAG, "No BOOTCLASSPATH found!");
498 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 /**
501 * Also ensure all external libraries have had dexopt run on them.
502 */
503 if (mSharedLibraries.size() > 0) {
504 Iterator<String> libs = mSharedLibraries.values().iterator();
505 while (libs.hasNext()) {
506 String lib = libs.next();
507 try {
508 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
509 libFiles.add(lib);
510 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700511 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 }
513 } catch (FileNotFoundException e) {
514 Log.w(TAG, "Library not found: " + lib);
515 } catch (IOException e) {
516 Log.w(TAG, "Exception reading library: " + lib, e);
517 }
518 }
519 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521 // Gross hack for now: we know this file doesn't contain any
522 // code, so don't dexopt it to avoid the resulting log spew.
523 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 /**
526 * And there are a number of commands implemented in Java, which
527 * we currently need to do the dexopt on so that they can be
528 * run from a non-root shell.
529 */
530 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700531 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 for (int i=0; i<frameworkFiles.length; i++) {
533 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
534 String path = libPath.getPath();
535 // Skip the file if we alrady did it.
536 if (libFiles.contains(path)) {
537 continue;
538 }
539 // Skip the file if it is not a type we want to dexopt.
540 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
541 continue;
542 }
543 try {
544 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
545 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700546 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 }
548 } catch (FileNotFoundException e) {
549 Log.w(TAG, "Jar not found: " + path);
550 } catch (IOException e) {
551 Log.w(TAG, "Exception reading jar: " + path, e);
552 }
553 }
554 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800555
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700556 if (didDexOpt) {
557 // If we had to do a dexopt of one of the previous
558 // things, then something on the system has changed.
559 // Consider this significant, and wipe away all other
560 // existing dexopt files to ensure we don't leave any
561 // dangling around.
562 String[] files = mDalvikCacheDir.list();
563 if (files != null) {
564 for (int i=0; i<files.length; i++) {
565 String fn = files[i];
566 if (fn.startsWith("data@app@")
567 || fn.startsWith("data@app-private@")) {
568 Log.i(TAG, "Pruning dalvik file: " + fn);
569 (new File(mDalvikCacheDir, fn)).delete();
570 }
571 }
572 }
573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 mFrameworkInstallObserver = new AppDirObserver(
577 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
578 mFrameworkInstallObserver.startWatching();
579 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800580 scanMode | SCAN_NO_DEX);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
582 mSystemInstallObserver = new AppDirObserver(
583 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
584 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800585 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 mAppInstallDir = new File(dataDir, "app");
587 if (mInstaller == null) {
588 // Make sure these dirs exist, when we are running in
589 // the simulator.
590 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
591 }
592 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800593 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 //clean up list
595 for(int i = 0; i < deletePkgsList.size(); i++) {
596 //clean up here
597 cleanupInstallFailedPackage(deletePkgsList.get(i));
598 }
599 //delete tmp files
600 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800601
602 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 SystemClock.uptimeMillis());
604 mAppInstallObserver = new AppDirObserver(
605 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
606 mAppInstallObserver.startWatching();
607 scanDirLI(mAppInstallDir, 0, scanMode);
608
609 mDrmAppInstallObserver = new AppDirObserver(
610 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
611 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800612 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800614 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 SystemClock.uptimeMillis());
616 Log.i(TAG, "Time to scan packages: "
617 + ((SystemClock.uptimeMillis()-startTime)/1000f)
618 + " seconds");
619
620 updatePermissionsLP();
621
622 mSettings.writeLP();
623
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800624 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 // Now after opening every single application zip, make sure they
628 // are all flushed. Not really needed, but keeps things nice and
629 // tidy.
630 Runtime.getRuntime().gc();
631 } // synchronized (mPackages)
632 } // synchronized (mInstallLock)
633 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 @Override
636 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
637 throws RemoteException {
638 try {
639 return super.onTransact(code, data, reply, flags);
640 } catch (RuntimeException e) {
641 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
642 Log.e(TAG, "Package Manager Crash", e);
643 }
644 throw e;
645 }
646 }
647
Oscar Montemayora8529f62009-11-18 10:14:20 -0800648 void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800650 boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
651 int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 if (retCode < 0) {
653 Log.w(TAG, "Couldn't remove app data directory for package: "
Oscar Montemayora8529f62009-11-18 10:14:20 -0800654 + pkgSettings.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 }
656 } else {
657 //for emulator
Oscar Montemayora8529f62009-11-18 10:14:20 -0800658 File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 dataDir.delete();
660 }
Oscar Montemayora8529f62009-11-18 10:14:20 -0800661 mSettings.removePackageLP(pkgSettings.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 }
663
664 void readPermissions() {
665 // Read permissions from .../etc/permission directory.
666 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
667 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
668 Log.w(TAG, "No directory " + libraryDir + ", skipping");
669 return;
670 }
671 if (!libraryDir.canRead()) {
672 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
673 return;
674 }
675
676 // Iterate over the files in the directory and scan .xml files
677 for (File f : libraryDir.listFiles()) {
678 // We'll read platform.xml last
679 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
680 continue;
681 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 if (!f.getPath().endsWith(".xml")) {
684 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
685 continue;
686 }
687 if (!f.canRead()) {
688 Log.w(TAG, "Permissions library file " + f + " cannot be read");
689 continue;
690 }
691
692 readPermissionsFromXml(f);
693 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
696 final File permFile = new File(Environment.getRootDirectory(),
697 "etc/permissions/platform.xml");
698 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800699
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700700 StringBuilder sb = new StringBuilder(128);
701 sb.append("Libs:");
702 Iterator<String> it = mSharedLibraries.keySet().iterator();
703 while (it.hasNext()) {
704 sb.append(' ');
705 String name = it.next();
706 sb.append(name);
707 sb.append(':');
708 sb.append(mSharedLibraries.get(name));
709 }
710 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800711
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700712 sb.setLength(0);
713 sb.append("Features:");
714 it = mAvailableFeatures.keySet().iterator();
715 while (it.hasNext()) {
716 sb.append(' ');
717 sb.append(it.next());
718 }
719 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800721
722 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 FileReader permReader = null;
724 try {
725 permReader = new FileReader(permFile);
726 } catch (FileNotFoundException e) {
727 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
728 return;
729 }
730
731 try {
732 XmlPullParser parser = Xml.newPullParser();
733 parser.setInput(permReader);
734
735 XmlUtils.beginDocument(parser, "permissions");
736
737 while (true) {
738 XmlUtils.nextElement(parser);
739 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
740 break;
741 }
742
743 String name = parser.getName();
744 if ("group".equals(name)) {
745 String gidStr = parser.getAttributeValue(null, "gid");
746 if (gidStr != null) {
747 int gid = Integer.parseInt(gidStr);
748 mGlobalGids = appendInt(mGlobalGids, gid);
749 } else {
750 Log.w(TAG, "<group> without gid at "
751 + parser.getPositionDescription());
752 }
753
754 XmlUtils.skipCurrentTag(parser);
755 continue;
756 } else if ("permission".equals(name)) {
757 String perm = parser.getAttributeValue(null, "name");
758 if (perm == null) {
759 Log.w(TAG, "<permission> without name at "
760 + parser.getPositionDescription());
761 XmlUtils.skipCurrentTag(parser);
762 continue;
763 }
764 perm = perm.intern();
765 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 } else if ("assign-permission".equals(name)) {
768 String perm = parser.getAttributeValue(null, "name");
769 if (perm == null) {
770 Log.w(TAG, "<assign-permission> without name at "
771 + parser.getPositionDescription());
772 XmlUtils.skipCurrentTag(parser);
773 continue;
774 }
775 String uidStr = parser.getAttributeValue(null, "uid");
776 if (uidStr == null) {
777 Log.w(TAG, "<assign-permission> without uid at "
778 + parser.getPositionDescription());
779 XmlUtils.skipCurrentTag(parser);
780 continue;
781 }
782 int uid = Process.getUidForName(uidStr);
783 if (uid < 0) {
784 Log.w(TAG, "<assign-permission> with unknown uid \""
785 + uidStr + "\" at "
786 + parser.getPositionDescription());
787 XmlUtils.skipCurrentTag(parser);
788 continue;
789 }
790 perm = perm.intern();
791 HashSet<String> perms = mSystemPermissions.get(uid);
792 if (perms == null) {
793 perms = new HashSet<String>();
794 mSystemPermissions.put(uid, perms);
795 }
796 perms.add(perm);
797 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 } else if ("library".equals(name)) {
800 String lname = parser.getAttributeValue(null, "name");
801 String lfile = parser.getAttributeValue(null, "file");
802 if (lname == null) {
803 Log.w(TAG, "<library> without name at "
804 + parser.getPositionDescription());
805 } else if (lfile == null) {
806 Log.w(TAG, "<library> without file at "
807 + parser.getPositionDescription());
808 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700809 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700810 mSharedLibraries.put(lname, lfile);
811 }
812 XmlUtils.skipCurrentTag(parser);
813 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800814
Dianne Hackborn49237342009-08-27 20:08:01 -0700815 } else if ("feature".equals(name)) {
816 String fname = parser.getAttributeValue(null, "name");
817 if (fname == null) {
818 Log.w(TAG, "<feature> without name at "
819 + parser.getPositionDescription());
820 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700821 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700822 FeatureInfo fi = new FeatureInfo();
823 fi.name = fname;
824 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 }
826 XmlUtils.skipCurrentTag(parser);
827 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 } else {
830 XmlUtils.skipCurrentTag(parser);
831 continue;
832 }
833
834 }
835 } catch (XmlPullParserException e) {
836 Log.w(TAG, "Got execption parsing permissions.", e);
837 } catch (IOException e) {
838 Log.w(TAG, "Got execption parsing permissions.", e);
839 }
840 }
841
842 void readPermission(XmlPullParser parser, String name)
843 throws IOException, XmlPullParserException {
844
845 name = name.intern();
846
847 BasePermission bp = mSettings.mPermissions.get(name);
848 if (bp == null) {
849 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
850 mSettings.mPermissions.put(name, bp);
851 }
852 int outerDepth = parser.getDepth();
853 int type;
854 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
855 && (type != XmlPullParser.END_TAG
856 || parser.getDepth() > outerDepth)) {
857 if (type == XmlPullParser.END_TAG
858 || type == XmlPullParser.TEXT) {
859 continue;
860 }
861
862 String tagName = parser.getName();
863 if ("group".equals(tagName)) {
864 String gidStr = parser.getAttributeValue(null, "gid");
865 if (gidStr != null) {
866 int gid = Process.getGidForName(gidStr);
867 bp.gids = appendInt(bp.gids, gid);
868 } else {
869 Log.w(TAG, "<group> without gid at "
870 + parser.getPositionDescription());
871 }
872 }
873 XmlUtils.skipCurrentTag(parser);
874 }
875 }
876
877 static int[] appendInt(int[] cur, int val) {
878 if (cur == null) {
879 return new int[] { val };
880 }
881 final int N = cur.length;
882 for (int i=0; i<N; i++) {
883 if (cur[i] == val) {
884 return cur;
885 }
886 }
887 int[] ret = new int[N+1];
888 System.arraycopy(cur, 0, ret, 0, N);
889 ret[N] = val;
890 return ret;
891 }
892
893 static int[] appendInts(int[] cur, int[] add) {
894 if (add == null) return cur;
895 if (cur == null) return add;
896 final int N = add.length;
897 for (int i=0; i<N; i++) {
898 cur = appendInt(cur, add[i]);
899 }
900 return cur;
901 }
902
903 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700904 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
905 // The package has been uninstalled but has retained data and resources.
906 return PackageParser.generatePackageInfo(p, null, flags);
907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 final PackageSetting ps = (PackageSetting)p.mExtras;
909 if (ps == null) {
910 return null;
911 }
912 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
913 return PackageParser.generatePackageInfo(p, gp.gids, flags);
914 }
915
916 public PackageInfo getPackageInfo(String packageName, int flags) {
917 synchronized (mPackages) {
918 PackageParser.Package p = mPackages.get(packageName);
919 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700920 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 + ": " + p);
922 if (p != null) {
923 return generatePackageInfo(p, flags);
924 }
925 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
926 return generatePackageInfoFromSettingsLP(packageName, flags);
927 }
928 }
929 return null;
930 }
931
932 public int getPackageUid(String packageName) {
933 synchronized (mPackages) {
934 PackageParser.Package p = mPackages.get(packageName);
935 if(p != null) {
936 return p.applicationInfo.uid;
937 }
938 PackageSetting ps = mSettings.mPackages.get(packageName);
939 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
940 return -1;
941 }
942 p = ps.pkg;
943 return p != null ? p.applicationInfo.uid : -1;
944 }
945 }
946
947 public int[] getPackageGids(String packageName) {
948 synchronized (mPackages) {
949 PackageParser.Package p = mPackages.get(packageName);
950 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700951 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 + ": " + p);
953 if (p != null) {
954 final PackageSetting ps = (PackageSetting)p.mExtras;
955 final SharedUserSetting suid = ps.sharedUser;
956 return suid != null ? suid.gids : ps.gids;
957 }
958 }
959 // stupid thing to indicate an error.
960 return new int[0];
961 }
962
963 public PermissionInfo getPermissionInfo(String name, int flags) {
964 synchronized (mPackages) {
965 final BasePermission p = mSettings.mPermissions.get(name);
966 if (p != null && p.perm != null) {
967 return PackageParser.generatePermissionInfo(p.perm, flags);
968 }
969 return null;
970 }
971 }
972
973 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
974 synchronized (mPackages) {
975 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
976 for (BasePermission p : mSettings.mPermissions.values()) {
977 if (group == null) {
978 if (p.perm.info.group == null) {
979 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
980 }
981 } else {
982 if (group.equals(p.perm.info.group)) {
983 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
984 }
985 }
986 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 if (out.size() > 0) {
989 return out;
990 }
991 return mPermissionGroups.containsKey(group) ? out : null;
992 }
993 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
996 synchronized (mPackages) {
997 return PackageParser.generatePermissionGroupInfo(
998 mPermissionGroups.get(name), flags);
999 }
1000 }
1001
1002 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1003 synchronized (mPackages) {
1004 final int N = mPermissionGroups.size();
1005 ArrayList<PermissionGroupInfo> out
1006 = new ArrayList<PermissionGroupInfo>(N);
1007 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1008 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1009 }
1010 return out;
1011 }
1012 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1015 PackageSetting ps = mSettings.mPackages.get(packageName);
1016 if(ps != null) {
1017 if(ps.pkg == null) {
1018 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1019 if(pInfo != null) {
1020 return pInfo.applicationInfo;
1021 }
1022 return null;
1023 }
1024 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1025 }
1026 return null;
1027 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1030 PackageSetting ps = mSettings.mPackages.get(packageName);
1031 if(ps != null) {
1032 if(ps.pkg == null) {
1033 ps.pkg = new PackageParser.Package(packageName);
1034 ps.pkg.applicationInfo.packageName = packageName;
1035 }
1036 return generatePackageInfo(ps.pkg, flags);
1037 }
1038 return null;
1039 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1042 synchronized (mPackages) {
1043 PackageParser.Package p = mPackages.get(packageName);
1044 if (Config.LOGV) Log.v(
1045 TAG, "getApplicationInfo " + packageName
1046 + ": " + p);
1047 if (p != null) {
1048 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001049 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 }
1051 if ("android".equals(packageName)||"system".equals(packageName)) {
1052 return mAndroidApplication;
1053 }
1054 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1055 return generateApplicationInfoFromSettingsLP(packageName, flags);
1056 }
1057 }
1058 return null;
1059 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001060
1061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1063 mContext.enforceCallingOrSelfPermission(
1064 android.Manifest.permission.CLEAR_APP_CACHE, null);
1065 // Queue up an async operation since clearing cache may take a little while.
1066 mHandler.post(new Runnable() {
1067 public void run() {
1068 mHandler.removeCallbacks(this);
1069 int retCode = -1;
1070 if (mInstaller != null) {
1071 retCode = mInstaller.freeCache(freeStorageSize);
1072 if (retCode < 0) {
1073 Log.w(TAG, "Couldn't clear application caches");
1074 }
1075 } //end if mInstaller
1076 if (observer != null) {
1077 try {
1078 observer.onRemoveCompleted(null, (retCode >= 0));
1079 } catch (RemoteException e) {
1080 Log.w(TAG, "RemoveException when invoking call back");
1081 }
1082 }
1083 }
1084 });
1085 }
1086
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001087 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001088 mContext.enforceCallingOrSelfPermission(
1089 android.Manifest.permission.CLEAR_APP_CACHE, null);
1090 // Queue up an async operation since clearing cache may take a little while.
1091 mHandler.post(new Runnable() {
1092 public void run() {
1093 mHandler.removeCallbacks(this);
1094 int retCode = -1;
1095 if (mInstaller != null) {
1096 retCode = mInstaller.freeCache(freeStorageSize);
1097 if (retCode < 0) {
1098 Log.w(TAG, "Couldn't clear application caches");
1099 }
1100 }
1101 if(pi != null) {
1102 try {
1103 // Callback via pending intent
1104 int code = (retCode >= 0) ? 1 : 0;
1105 pi.sendIntent(null, code, null,
1106 null, null);
1107 } catch (SendIntentException e1) {
1108 Log.i(TAG, "Failed to send pending intent");
1109 }
1110 }
1111 }
1112 });
1113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1116 synchronized (mPackages) {
1117 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001118
1119 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001121 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 }
1123 if (mResolveComponentName.equals(component)) {
1124 return mResolveActivity;
1125 }
1126 }
1127 return null;
1128 }
1129
1130 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1131 synchronized (mPackages) {
1132 PackageParser.Activity a = mReceivers.mActivities.get(component);
1133 if (Config.LOGV) Log.v(
1134 TAG, "getReceiverInfo " + component + ": " + a);
1135 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1136 return PackageParser.generateActivityInfo(a, flags);
1137 }
1138 }
1139 return null;
1140 }
1141
1142 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1143 synchronized (mPackages) {
1144 PackageParser.Service s = mServices.mServices.get(component);
1145 if (Config.LOGV) Log.v(
1146 TAG, "getServiceInfo " + component + ": " + s);
1147 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1148 return PackageParser.generateServiceInfo(s, flags);
1149 }
1150 }
1151 return null;
1152 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 public String[] getSystemSharedLibraryNames() {
1155 Set<String> libSet;
1156 synchronized (mPackages) {
1157 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001158 int size = libSet.size();
1159 if (size > 0) {
1160 String[] libs = new String[size];
1161 libSet.toArray(libs);
1162 return libs;
1163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001165 return null;
1166 }
1167
1168 public FeatureInfo[] getSystemAvailableFeatures() {
1169 Collection<FeatureInfo> featSet;
1170 synchronized (mPackages) {
1171 featSet = mAvailableFeatures.values();
1172 int size = featSet.size();
1173 if (size > 0) {
1174 FeatureInfo[] features = new FeatureInfo[size+1];
1175 featSet.toArray(features);
1176 FeatureInfo fi = new FeatureInfo();
1177 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1178 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1179 features[size] = fi;
1180 return features;
1181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 }
1183 return null;
1184 }
1185
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001186 public boolean hasSystemFeature(String name) {
1187 synchronized (mPackages) {
1188 return mAvailableFeatures.containsKey(name);
1189 }
1190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 public int checkPermission(String permName, String pkgName) {
1193 synchronized (mPackages) {
1194 PackageParser.Package p = mPackages.get(pkgName);
1195 if (p != null && p.mExtras != null) {
1196 PackageSetting ps = (PackageSetting)p.mExtras;
1197 if (ps.sharedUser != null) {
1198 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1199 return PackageManager.PERMISSION_GRANTED;
1200 }
1201 } else if (ps.grantedPermissions.contains(permName)) {
1202 return PackageManager.PERMISSION_GRANTED;
1203 }
1204 }
1205 }
1206 return PackageManager.PERMISSION_DENIED;
1207 }
1208
1209 public int checkUidPermission(String permName, int uid) {
1210 synchronized (mPackages) {
1211 Object obj = mSettings.getUserIdLP(uid);
1212 if (obj != null) {
1213 if (obj instanceof SharedUserSetting) {
1214 SharedUserSetting sus = (SharedUserSetting)obj;
1215 if (sus.grantedPermissions.contains(permName)) {
1216 return PackageManager.PERMISSION_GRANTED;
1217 }
1218 } else if (obj instanceof PackageSetting) {
1219 PackageSetting ps = (PackageSetting)obj;
1220 if (ps.grantedPermissions.contains(permName)) {
1221 return PackageManager.PERMISSION_GRANTED;
1222 }
1223 }
1224 } else {
1225 HashSet<String> perms = mSystemPermissions.get(uid);
1226 if (perms != null && perms.contains(permName)) {
1227 return PackageManager.PERMISSION_GRANTED;
1228 }
1229 }
1230 }
1231 return PackageManager.PERMISSION_DENIED;
1232 }
1233
1234 private BasePermission findPermissionTreeLP(String permName) {
1235 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1236 if (permName.startsWith(bp.name) &&
1237 permName.length() > bp.name.length() &&
1238 permName.charAt(bp.name.length()) == '.') {
1239 return bp;
1240 }
1241 }
1242 return null;
1243 }
1244
1245 private BasePermission checkPermissionTreeLP(String permName) {
1246 if (permName != null) {
1247 BasePermission bp = findPermissionTreeLP(permName);
1248 if (bp != null) {
1249 if (bp.uid == Binder.getCallingUid()) {
1250 return bp;
1251 }
1252 throw new SecurityException("Calling uid "
1253 + Binder.getCallingUid()
1254 + " is not allowed to add to permission tree "
1255 + bp.name + " owned by uid " + bp.uid);
1256 }
1257 }
1258 throw new SecurityException("No permission tree found for " + permName);
1259 }
1260
1261 public boolean addPermission(PermissionInfo info) {
1262 synchronized (mPackages) {
1263 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1264 throw new SecurityException("Label must be specified in permission");
1265 }
1266 BasePermission tree = checkPermissionTreeLP(info.name);
1267 BasePermission bp = mSettings.mPermissions.get(info.name);
1268 boolean added = bp == null;
1269 if (added) {
1270 bp = new BasePermission(info.name, tree.sourcePackage,
1271 BasePermission.TYPE_DYNAMIC);
1272 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1273 throw new SecurityException(
1274 "Not allowed to modify non-dynamic permission "
1275 + info.name);
1276 }
1277 bp.perm = new PackageParser.Permission(tree.perm.owner,
1278 new PermissionInfo(info));
1279 bp.perm.info.packageName = tree.perm.info.packageName;
1280 bp.uid = tree.uid;
1281 if (added) {
1282 mSettings.mPermissions.put(info.name, bp);
1283 }
1284 mSettings.writeLP();
1285 return added;
1286 }
1287 }
1288
1289 public void removePermission(String name) {
1290 synchronized (mPackages) {
1291 checkPermissionTreeLP(name);
1292 BasePermission bp = mSettings.mPermissions.get(name);
1293 if (bp != null) {
1294 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1295 throw new SecurityException(
1296 "Not allowed to modify non-dynamic permission "
1297 + name);
1298 }
1299 mSettings.mPermissions.remove(name);
1300 mSettings.writeLP();
1301 }
1302 }
1303 }
1304
Dianne Hackborn854060af2009-07-09 18:14:31 -07001305 public boolean isProtectedBroadcast(String actionName) {
1306 synchronized (mPackages) {
1307 return mProtectedBroadcasts.contains(actionName);
1308 }
1309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 public int checkSignatures(String pkg1, String pkg2) {
1312 synchronized (mPackages) {
1313 PackageParser.Package p1 = mPackages.get(pkg1);
1314 PackageParser.Package p2 = mPackages.get(pkg2);
1315 if (p1 == null || p1.mExtras == null
1316 || p2 == null || p2.mExtras == null) {
1317 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1318 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001319 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 }
1321 }
1322
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001323 public int checkUidSignatures(int uid1, int uid2) {
1324 synchronized (mPackages) {
1325 Signature[] s1;
1326 Signature[] s2;
1327 Object obj = mSettings.getUserIdLP(uid1);
1328 if (obj != null) {
1329 if (obj instanceof SharedUserSetting) {
1330 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1331 } else if (obj instanceof PackageSetting) {
1332 s1 = ((PackageSetting)obj).signatures.mSignatures;
1333 } else {
1334 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1335 }
1336 } else {
1337 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1338 }
1339 obj = mSettings.getUserIdLP(uid2);
1340 if (obj != null) {
1341 if (obj instanceof SharedUserSetting) {
1342 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1343 } else if (obj instanceof PackageSetting) {
1344 s2 = ((PackageSetting)obj).signatures.mSignatures;
1345 } else {
1346 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1347 }
1348 } else {
1349 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1350 }
1351 return checkSignaturesLP(s1, s2);
1352 }
1353 }
1354
1355 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1356 if (s1 == null) {
1357 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1359 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1360 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001361 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1363 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001364 final int N1 = s1.length;
1365 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 for (int i=0; i<N1; i++) {
1367 boolean match = false;
1368 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001369 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 match = true;
1371 break;
1372 }
1373 }
1374 if (!match) {
1375 return PackageManager.SIGNATURE_NO_MATCH;
1376 }
1377 }
1378 return PackageManager.SIGNATURE_MATCH;
1379 }
1380
1381 public String[] getPackagesForUid(int uid) {
1382 synchronized (mPackages) {
1383 Object obj = mSettings.getUserIdLP(uid);
1384 if (obj instanceof SharedUserSetting) {
1385 SharedUserSetting sus = (SharedUserSetting)obj;
1386 final int N = sus.packages.size();
1387 String[] res = new String[N];
1388 Iterator<PackageSetting> it = sus.packages.iterator();
1389 int i=0;
1390 while (it.hasNext()) {
1391 res[i++] = it.next().name;
1392 }
1393 return res;
1394 } else if (obj instanceof PackageSetting) {
1395 PackageSetting ps = (PackageSetting)obj;
1396 return new String[] { ps.name };
1397 }
1398 }
1399 return null;
1400 }
1401
1402 public String getNameForUid(int uid) {
1403 synchronized (mPackages) {
1404 Object obj = mSettings.getUserIdLP(uid);
1405 if (obj instanceof SharedUserSetting) {
1406 SharedUserSetting sus = (SharedUserSetting)obj;
1407 return sus.name + ":" + sus.userId;
1408 } else if (obj instanceof PackageSetting) {
1409 PackageSetting ps = (PackageSetting)obj;
1410 return ps.name;
1411 }
1412 }
1413 return null;
1414 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 public int getUidForSharedUser(String sharedUserName) {
1417 if(sharedUserName == null) {
1418 return -1;
1419 }
1420 synchronized (mPackages) {
1421 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1422 if(suid == null) {
1423 return -1;
1424 }
1425 return suid.userId;
1426 }
1427 }
1428
1429 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1430 int flags) {
1431 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001432 return chooseBestActivity(intent, resolvedType, flags, query);
1433 }
1434
Mihai Predaeae850c2009-05-13 10:13:48 +02001435 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1436 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 if (query != null) {
1438 final int N = query.size();
1439 if (N == 1) {
1440 return query.get(0);
1441 } else if (N > 1) {
1442 // If there is more than one activity with the same priority,
1443 // then let the user decide between them.
1444 ResolveInfo r0 = query.get(0);
1445 ResolveInfo r1 = query.get(1);
1446 if (false) {
1447 System.out.println(r0.activityInfo.name +
1448 "=" + r0.priority + " vs " +
1449 r1.activityInfo.name +
1450 "=" + r1.priority);
1451 }
1452 // If the first activity has a higher priority, or a different
1453 // default, then it is always desireable to pick it.
1454 if (r0.priority != r1.priority
1455 || r0.preferredOrder != r1.preferredOrder
1456 || r0.isDefault != r1.isDefault) {
1457 return query.get(0);
1458 }
1459 // If we have saved a preference for a preferred activity for
1460 // this Intent, use that.
1461 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1462 flags, query, r0.priority);
1463 if (ri != null) {
1464 return ri;
1465 }
1466 return mResolveInfo;
1467 }
1468 }
1469 return null;
1470 }
1471
1472 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1473 int flags, List<ResolveInfo> query, int priority) {
1474 synchronized (mPackages) {
1475 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1476 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001477 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1479 if (prefs != null && prefs.size() > 0) {
1480 // First figure out how good the original match set is.
1481 // We will only allow preferred activities that came
1482 // from the same match quality.
1483 int match = 0;
1484 final int N = query.size();
1485 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1486 for (int j=0; j<N; j++) {
1487 ResolveInfo ri = query.get(j);
1488 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1489 + ": 0x" + Integer.toHexString(match));
1490 if (ri.match > match) match = ri.match;
1491 }
1492 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1493 + Integer.toHexString(match));
1494 match &= IntentFilter.MATCH_CATEGORY_MASK;
1495 final int M = prefs.size();
1496 for (int i=0; i<M; i++) {
1497 PreferredActivity pa = prefs.get(i);
1498 if (pa.mMatch != match) {
1499 continue;
1500 }
1501 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1502 if (DEBUG_PREFERRED) {
1503 Log.v(TAG, "Got preferred activity:");
1504 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1505 }
1506 if (ai != null) {
1507 for (int j=0; j<N; j++) {
1508 ResolveInfo ri = query.get(j);
1509 if (!ri.activityInfo.applicationInfo.packageName
1510 .equals(ai.applicationInfo.packageName)) {
1511 continue;
1512 }
1513 if (!ri.activityInfo.name.equals(ai.name)) {
1514 continue;
1515 }
1516
1517 // Okay we found a previously set preferred app.
1518 // If the result set is different from when this
1519 // was created, we need to clear it and re-ask the
1520 // user their preference.
1521 if (!pa.sameSet(query, priority)) {
1522 Log.i(TAG, "Result set changed, dropping preferred activity for "
1523 + intent + " type " + resolvedType);
1524 mSettings.mPreferredActivities.removeFilter(pa);
1525 return null;
1526 }
1527
1528 // Yay!
1529 return ri;
1530 }
1531 }
1532 }
1533 }
1534 }
1535 return null;
1536 }
1537
1538 public List<ResolveInfo> queryIntentActivities(Intent intent,
1539 String resolvedType, int flags) {
1540 ComponentName comp = intent.getComponent();
1541 if (comp != null) {
1542 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1543 ActivityInfo ai = getActivityInfo(comp, flags);
1544 if (ai != null) {
1545 ResolveInfo ri = new ResolveInfo();
1546 ri.activityInfo = ai;
1547 list.add(ri);
1548 }
1549 return list;
1550 }
1551
1552 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001553 String pkgName = intent.getPackage();
1554 if (pkgName == null) {
1555 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1556 resolvedType, flags);
1557 }
1558 PackageParser.Package pkg = mPackages.get(pkgName);
1559 if (pkg != null) {
1560 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1561 resolvedType, flags, pkg.activities);
1562 }
1563 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 }
1565 }
1566
1567 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1568 Intent[] specifics, String[] specificTypes, Intent intent,
1569 String resolvedType, int flags) {
1570 final String resultsAction = intent.getAction();
1571
1572 List<ResolveInfo> results = queryIntentActivities(
1573 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1574 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1575
1576 int specificsPos = 0;
1577 int N;
1578
1579 // todo: note that the algorithm used here is O(N^2). This
1580 // isn't a problem in our current environment, but if we start running
1581 // into situations where we have more than 5 or 10 matches then this
1582 // should probably be changed to something smarter...
1583
1584 // First we go through and resolve each of the specific items
1585 // that were supplied, taking care of removing any corresponding
1586 // duplicate items in the generic resolve list.
1587 if (specifics != null) {
1588 for (int i=0; i<specifics.length; i++) {
1589 final Intent sintent = specifics[i];
1590 if (sintent == null) {
1591 continue;
1592 }
1593
1594 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1595 String action = sintent.getAction();
1596 if (resultsAction != null && resultsAction.equals(action)) {
1597 // If this action was explicitly requested, then don't
1598 // remove things that have it.
1599 action = null;
1600 }
1601 ComponentName comp = sintent.getComponent();
1602 ResolveInfo ri = null;
1603 ActivityInfo ai = null;
1604 if (comp == null) {
1605 ri = resolveIntent(
1606 sintent,
1607 specificTypes != null ? specificTypes[i] : null,
1608 flags);
1609 if (ri == null) {
1610 continue;
1611 }
1612 if (ri == mResolveInfo) {
1613 // ACK! Must do something better with this.
1614 }
1615 ai = ri.activityInfo;
1616 comp = new ComponentName(ai.applicationInfo.packageName,
1617 ai.name);
1618 } else {
1619 ai = getActivityInfo(comp, flags);
1620 if (ai == null) {
1621 continue;
1622 }
1623 }
1624
1625 // Look for any generic query activities that are duplicates
1626 // of this specific one, and remove them from the results.
1627 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1628 N = results.size();
1629 int j;
1630 for (j=specificsPos; j<N; j++) {
1631 ResolveInfo sri = results.get(j);
1632 if ((sri.activityInfo.name.equals(comp.getClassName())
1633 && sri.activityInfo.applicationInfo.packageName.equals(
1634 comp.getPackageName()))
1635 || (action != null && sri.filter.matchAction(action))) {
1636 results.remove(j);
1637 if (Config.LOGV) Log.v(
1638 TAG, "Removing duplicate item from " + j
1639 + " due to specific " + specificsPos);
1640 if (ri == null) {
1641 ri = sri;
1642 }
1643 j--;
1644 N--;
1645 }
1646 }
1647
1648 // Add this specific item to its proper place.
1649 if (ri == null) {
1650 ri = new ResolveInfo();
1651 ri.activityInfo = ai;
1652 }
1653 results.add(specificsPos, ri);
1654 ri.specificIndex = i;
1655 specificsPos++;
1656 }
1657 }
1658
1659 // Now we go through the remaining generic results and remove any
1660 // duplicate actions that are found here.
1661 N = results.size();
1662 for (int i=specificsPos; i<N-1; i++) {
1663 final ResolveInfo rii = results.get(i);
1664 if (rii.filter == null) {
1665 continue;
1666 }
1667
1668 // Iterate over all of the actions of this result's intent
1669 // filter... typically this should be just one.
1670 final Iterator<String> it = rii.filter.actionsIterator();
1671 if (it == null) {
1672 continue;
1673 }
1674 while (it.hasNext()) {
1675 final String action = it.next();
1676 if (resultsAction != null && resultsAction.equals(action)) {
1677 // If this action was explicitly requested, then don't
1678 // remove things that have it.
1679 continue;
1680 }
1681 for (int j=i+1; j<N; j++) {
1682 final ResolveInfo rij = results.get(j);
1683 if (rij.filter != null && rij.filter.hasAction(action)) {
1684 results.remove(j);
1685 if (Config.LOGV) Log.v(
1686 TAG, "Removing duplicate item from " + j
1687 + " due to action " + action + " at " + i);
1688 j--;
1689 N--;
1690 }
1691 }
1692 }
1693
1694 // If the caller didn't request filter information, drop it now
1695 // so we don't have to marshall/unmarshall it.
1696 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1697 rii.filter = null;
1698 }
1699 }
1700
1701 // Filter out the caller activity if so requested.
1702 if (caller != null) {
1703 N = results.size();
1704 for (int i=0; i<N; i++) {
1705 ActivityInfo ainfo = results.get(i).activityInfo;
1706 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1707 && caller.getClassName().equals(ainfo.name)) {
1708 results.remove(i);
1709 break;
1710 }
1711 }
1712 }
1713
1714 // If the caller didn't request filter information,
1715 // drop them now so we don't have to
1716 // marshall/unmarshall it.
1717 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1718 N = results.size();
1719 for (int i=0; i<N; i++) {
1720 results.get(i).filter = null;
1721 }
1722 }
1723
1724 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1725 return results;
1726 }
1727
1728 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1729 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001730 ComponentName comp = intent.getComponent();
1731 if (comp != null) {
1732 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1733 ActivityInfo ai = getReceiverInfo(comp, flags);
1734 if (ai != null) {
1735 ResolveInfo ri = new ResolveInfo();
1736 ri.activityInfo = ai;
1737 list.add(ri);
1738 }
1739 return list;
1740 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001743 String pkgName = intent.getPackage();
1744 if (pkgName == null) {
1745 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1746 resolvedType, flags);
1747 }
1748 PackageParser.Package pkg = mPackages.get(pkgName);
1749 if (pkg != null) {
1750 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1751 resolvedType, flags, pkg.receivers);
1752 }
1753 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 }
1755 }
1756
1757 public ResolveInfo resolveService(Intent intent, String resolvedType,
1758 int flags) {
1759 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1760 flags);
1761 if (query != null) {
1762 if (query.size() >= 1) {
1763 // If there is more than one service with the same priority,
1764 // just arbitrarily pick the first one.
1765 return query.get(0);
1766 }
1767 }
1768 return null;
1769 }
1770
1771 public List<ResolveInfo> queryIntentServices(Intent intent,
1772 String resolvedType, int flags) {
1773 ComponentName comp = intent.getComponent();
1774 if (comp != null) {
1775 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1776 ServiceInfo si = getServiceInfo(comp, flags);
1777 if (si != null) {
1778 ResolveInfo ri = new ResolveInfo();
1779 ri.serviceInfo = si;
1780 list.add(ri);
1781 }
1782 return list;
1783 }
1784
1785 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001786 String pkgName = intent.getPackage();
1787 if (pkgName == null) {
1788 return (List<ResolveInfo>)mServices.queryIntent(intent,
1789 resolvedType, flags);
1790 }
1791 PackageParser.Package pkg = mPackages.get(pkgName);
1792 if (pkg != null) {
1793 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1794 resolvedType, flags, pkg.services);
1795 }
1796 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 }
1798 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 public List<PackageInfo> getInstalledPackages(int flags) {
1801 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1802
1803 synchronized (mPackages) {
1804 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1805 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1806 while (i.hasNext()) {
1807 final PackageSetting ps = i.next();
1808 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1809 if(psPkg != null) {
1810 finalList.add(psPkg);
1811 }
1812 }
1813 }
1814 else {
1815 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1816 while (i.hasNext()) {
1817 final PackageParser.Package p = i.next();
1818 if (p.applicationInfo != null) {
1819 PackageInfo pi = generatePackageInfo(p, flags);
1820 if(pi != null) {
1821 finalList.add(pi);
1822 }
1823 }
1824 }
1825 }
1826 }
1827 return finalList;
1828 }
1829
1830 public List<ApplicationInfo> getInstalledApplications(int flags) {
1831 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1832 synchronized(mPackages) {
1833 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1834 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1835 while (i.hasNext()) {
1836 final PackageSetting ps = i.next();
1837 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1838 if(ai != null) {
1839 finalList.add(ai);
1840 }
1841 }
1842 }
1843 else {
1844 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1845 while (i.hasNext()) {
1846 final PackageParser.Package p = i.next();
1847 if (p.applicationInfo != null) {
1848 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1849 if(ai != null) {
1850 finalList.add(ai);
1851 }
1852 }
1853 }
1854 }
1855 }
1856 return finalList;
1857 }
1858
1859 public List<ApplicationInfo> getPersistentApplications(int flags) {
1860 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1861
1862 synchronized (mPackages) {
1863 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1864 while (i.hasNext()) {
1865 PackageParser.Package p = i.next();
1866 if (p.applicationInfo != null
1867 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1868 && (!mSafeMode || (p.applicationInfo.flags
1869 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1870 finalList.add(p.applicationInfo);
1871 }
1872 }
1873 }
1874
1875 return finalList;
1876 }
1877
1878 public ProviderInfo resolveContentProvider(String name, int flags) {
1879 synchronized (mPackages) {
1880 final PackageParser.Provider provider = mProviders.get(name);
1881 return provider != null
1882 && mSettings.isEnabledLP(provider.info, flags)
1883 && (!mSafeMode || (provider.info.applicationInfo.flags
1884 &ApplicationInfo.FLAG_SYSTEM) != 0)
1885 ? PackageParser.generateProviderInfo(provider, flags)
1886 : null;
1887 }
1888 }
1889
Fred Quintana718d8a22009-04-29 17:53:20 -07001890 /**
1891 * @deprecated
1892 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 public void querySyncProviders(List outNames, List outInfo) {
1894 synchronized (mPackages) {
1895 Iterator<Map.Entry<String, PackageParser.Provider>> i
1896 = mProviders.entrySet().iterator();
1897
1898 while (i.hasNext()) {
1899 Map.Entry<String, PackageParser.Provider> entry = i.next();
1900 PackageParser.Provider p = entry.getValue();
1901
1902 if (p.syncable
1903 && (!mSafeMode || (p.info.applicationInfo.flags
1904 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1905 outNames.add(entry.getKey());
1906 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1907 }
1908 }
1909 }
1910 }
1911
1912 public List<ProviderInfo> queryContentProviders(String processName,
1913 int uid, int flags) {
1914 ArrayList<ProviderInfo> finalList = null;
1915
1916 synchronized (mPackages) {
1917 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1918 while (i.hasNext()) {
1919 PackageParser.Provider p = i.next();
1920 if (p.info.authority != null
1921 && (processName == null ||
1922 (p.info.processName.equals(processName)
1923 && p.info.applicationInfo.uid == uid))
1924 && mSettings.isEnabledLP(p.info, flags)
1925 && (!mSafeMode || (p.info.applicationInfo.flags
1926 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1927 if (finalList == null) {
1928 finalList = new ArrayList<ProviderInfo>(3);
1929 }
1930 finalList.add(PackageParser.generateProviderInfo(p,
1931 flags));
1932 }
1933 }
1934 }
1935
1936 if (finalList != null) {
1937 Collections.sort(finalList, mProviderInitOrderSorter);
1938 }
1939
1940 return finalList;
1941 }
1942
1943 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1944 int flags) {
1945 synchronized (mPackages) {
1946 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1947 return PackageParser.generateInstrumentationInfo(i, flags);
1948 }
1949 }
1950
1951 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1952 int flags) {
1953 ArrayList<InstrumentationInfo> finalList =
1954 new ArrayList<InstrumentationInfo>();
1955
1956 synchronized (mPackages) {
1957 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1958 while (i.hasNext()) {
1959 PackageParser.Instrumentation p = i.next();
1960 if (targetPackage == null
1961 || targetPackage.equals(p.info.targetPackage)) {
1962 finalList.add(PackageParser.generateInstrumentationInfo(p,
1963 flags));
1964 }
1965 }
1966 }
1967
1968 return finalList;
1969 }
1970
1971 private void scanDirLI(File dir, int flags, int scanMode) {
1972 Log.d(TAG, "Scanning app dir " + dir);
1973
1974 String[] files = dir.list();
1975
1976 int i;
1977 for (i=0; i<files.length; i++) {
1978 File file = new File(dir, files[i]);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08001979 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1981 }
1982 }
1983
1984 private static void reportSettingsProblem(int priority, String msg) {
1985 try {
1986 File dataDir = Environment.getDataDirectory();
1987 File systemDir = new File(dataDir, "system");
1988 File fname = new File(systemDir, "uiderrors.txt");
1989 FileOutputStream out = new FileOutputStream(fname, true);
1990 PrintWriter pw = new PrintWriter(out);
1991 pw.println(msg);
1992 pw.close();
1993 FileUtils.setPermissions(
1994 fname.toString(),
1995 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1996 -1, -1);
1997 } catch (java.io.IOException e) {
1998 }
1999 Log.println(priority, TAG, msg);
2000 }
2001
2002 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2003 PackageParser.Package pkg, File srcFile, int parseFlags) {
2004 if (GET_CERTIFICATES) {
2005 if (ps == null || !ps.codePath.equals(srcFile)
2006 || ps.getTimeStamp() != srcFile.lastModified()) {
2007 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2008 if (!pp.collectCertificates(pkg, parseFlags)) {
2009 mLastScanError = pp.getParseError();
2010 return false;
2011 }
2012 }
2013 }
2014 return true;
2015 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 /*
2018 * Scan a package and return the newly parsed package.
2019 * Returns null in case of errors and the error code is stored in mLastScanError
2020 */
2021 private PackageParser.Package scanPackageLI(File scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002022 int parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 int scanMode) {
2024 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2025 parseFlags |= mDefParseFlags;
2026 PackageParser pp = new PackageParser(scanFile.getPath());
2027 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002029 scanFile.getPath(),
2030 mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 if (pkg == null) {
2032 mLastScanError = pp.getParseError();
2033 return null;
2034 }
2035 PackageSetting ps;
2036 PackageSetting updatedPkg;
2037 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002038 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2040 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002041 // Verify certificates first
2042 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2043 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2044 return null;
2045 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 if (updatedPkg != null) {
2047 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2048 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2049 }
2050 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2051 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002052 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2053 if (pkg.mVersionCode < ps.versionCode) {
2054 // The system package has been updated and the code path does not match
2055 // Ignore entry. Just return
2056 Log.w(TAG, "Package:" + pkg.packageName +
2057 " has been updated. Ignoring the one from path:"+scanFile);
2058 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2059 return null;
2060 } else {
2061 // Delete the older apk pointed to by ps
2062 // At this point, its safely assumed that package installation for
2063 // apps in system partition will go through. If not there won't be a working
2064 // version of the app
2065 synchronized (mPackages) {
2066 // Just remove the loaded entries from package lists.
2067 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002068 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002069 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2070 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 }
2073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 // The apk is forward locked (not public) if its code and resources
2075 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002076 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002078 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002081 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 }
2083
2084 private static String fixProcessName(String defProcessName,
2085 String processName, int uid) {
2086 if (processName == null) {
2087 return defProcessName;
2088 }
2089 return processName;
2090 }
2091
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002092 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2094 if (pkg.mSignatures != null) {
2095 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2096 updateSignature)) {
2097 Log.e(TAG, "Package " + pkg.packageName
2098 + " signatures do not match the previously installed version; ignoring!");
2099 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2100 return false;
2101 }
2102
2103 if (pkgSetting.sharedUser != null) {
2104 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2105 pkg.mSignatures, updateSignature)) {
2106 Log.e(TAG, "Package " + pkg.packageName
2107 + " has no signatures that match those in shared user "
2108 + pkgSetting.sharedUser.name + "; ignoring!");
2109 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2110 return false;
2111 }
2112 }
2113 } else {
2114 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2115 }
2116 return true;
2117 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002118
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002119 public boolean performDexOpt(String packageName) {
2120 if (!mNoDexOpt) {
2121 return false;
2122 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002123
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002124 PackageParser.Package p;
2125 synchronized (mPackages) {
2126 p = mPackages.get(packageName);
2127 if (p == null || p.mDidDexOpt) {
2128 return false;
2129 }
2130 }
2131 synchronized (mInstallLock) {
2132 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2133 }
2134 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002135
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002136 static final int DEX_OPT_SKIPPED = 0;
2137 static final int DEX_OPT_PERFORMED = 1;
2138 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002139
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002140 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2141 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002142 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002143 String path = pkg.mScanPath;
2144 int ret = 0;
2145 try {
2146 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002147 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002148 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002149 pkg.mDidDexOpt = true;
2150 performed = true;
2151 }
2152 } catch (FileNotFoundException e) {
2153 Log.w(TAG, "Apk not found for dexopt: " + path);
2154 ret = -1;
2155 } catch (IOException e) {
2156 Log.w(TAG, "Exception reading apk: " + path, e);
2157 ret = -1;
2158 }
2159 if (ret < 0) {
2160 //error from installer
2161 return DEX_OPT_FAILED;
2162 }
2163 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002164
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002165 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2166 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002167
2168 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2169 return Environment.isEncryptedFilesystemEnabled() &&
2170 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2171 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 private PackageParser.Package scanPackageLI(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 PackageParser.Package pkg, int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002175 File scanFile = new File(pkg.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 mScanningPath = scanFile;
2177 if (pkg == null) {
2178 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2179 return null;
2180 }
2181
2182 final String pkgName = pkg.applicationInfo.packageName;
2183 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2184 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2185 }
2186
2187 if (pkgName.equals("android")) {
2188 synchronized (mPackages) {
2189 if (mAndroidApplication != null) {
2190 Log.w(TAG, "*************************************************");
2191 Log.w(TAG, "Core android package being redefined. Skipping.");
2192 Log.w(TAG, " file=" + mScanningPath);
2193 Log.w(TAG, "*************************************************");
2194 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2195 return null;
2196 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 // Set up information for our fall-back user intent resolution
2199 // activity.
2200 mPlatformPackage = pkg;
2201 pkg.mVersionCode = mSdkVersion;
2202 mAndroidApplication = pkg.applicationInfo;
2203 mResolveActivity.applicationInfo = mAndroidApplication;
2204 mResolveActivity.name = ResolverActivity.class.getName();
2205 mResolveActivity.packageName = mAndroidApplication.packageName;
2206 mResolveActivity.processName = mAndroidApplication.processName;
2207 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2208 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2209 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2210 mResolveActivity.exported = true;
2211 mResolveActivity.enabled = true;
2212 mResolveInfo.activityInfo = mResolveActivity;
2213 mResolveInfo.priority = 0;
2214 mResolveInfo.preferredOrder = 0;
2215 mResolveInfo.match = 0;
2216 mResolveComponentName = new ComponentName(
2217 mAndroidApplication.packageName, mResolveActivity.name);
2218 }
2219 }
2220
2221 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2222 TAG, "Scanning package " + pkgName);
2223 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2224 Log.w(TAG, "*************************************************");
2225 Log.w(TAG, "Application package " + pkgName
2226 + " already installed. Skipping duplicate.");
2227 Log.w(TAG, "*************************************************");
2228 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2229 return null;
2230 }
2231
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002232 // Initialize package source and resource directories
2233 File destResourceFile = null;
2234 File destCodeFile = null;
2235 if ((scanMode & SCAN_NO_PATHS) == 0) {
2236 boolean fwdLocked = (parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0;
2237 final String pkgFileName = pkgName + ".apk";
2238 File destDir = null;
2239
2240 if (fwdLocked) {
2241 destDir = mDrmAppPrivateInstallDir;
2242 destResourceFile = new File(mAppInstallDir, pkgName + ".zip");
2243 } else {
2244 boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
2245 if (!onSd) {
2246 destDir = mAppInstallDir;
2247 } else {
2248 String cachePath = getSdDir(pkgName);
2249 if (cachePath == null) {
2250 Log.e(TAG, "Secure container path for pkg: " + pkgName + " at location: " + cachePath +
2251 " not found");
2252 mLastScanError = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
2253 return null;
2254 }
2255 destDir = new File(cachePath);
2256 }
2257 destResourceFile = new File(destDir, pkgFileName);
2258 }
2259 destCodeFile = new File(destDir, pkgFileName);
2260 pkg.mPath = destCodeFile.getAbsolutePath();
2261 } else {
2262 pkg.mPath = pkg.mScanPath;
2263 destCodeFile = new File(pkg.mScanPath);
2264 destResourceFile = new File(pkg.mScanPath);
2265 }
2266 pkg.applicationInfo.sourceDir = destCodeFile.getAbsolutePath();
2267 pkg.applicationInfo.publicSourceDir = destResourceFile.getAbsolutePath();
2268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 SharedUserSetting suid = null;
2270 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 synchronized (mPackages) {
2275 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002276 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2277 if (mTmpSharedLibraries == null ||
2278 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2279 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2280 }
2281 int num = 0;
2282 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2283 for (int i=0; i<N; i++) {
2284 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285 if (file == null) {
2286 Log.e(TAG, "Package " + pkg.packageName
2287 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002288 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2290 return null;
2291 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002292 mTmpSharedLibraries[num] = file;
2293 num++;
2294 }
2295 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2296 for (int i=0; i<N; i++) {
2297 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2298 if (file == null) {
2299 Log.w(TAG, "Package " + pkg.packageName
2300 + " desires unavailable shared library "
2301 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2302 } else {
2303 mTmpSharedLibraries[num] = file;
2304 num++;
2305 }
2306 }
2307 if (num > 0) {
2308 pkg.usesLibraryFiles = new String[num];
2309 System.arraycopy(mTmpSharedLibraries, 0,
2310 pkg.usesLibraryFiles, 0, num);
2311 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002312
Dianne Hackborn49237342009-08-27 20:08:01 -07002313 if (pkg.reqFeatures != null) {
2314 N = pkg.reqFeatures.size();
2315 for (int i=0; i<N; i++) {
2316 FeatureInfo fi = pkg.reqFeatures.get(i);
2317 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2318 // Don't care.
2319 continue;
2320 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002321
Dianne Hackborn49237342009-08-27 20:08:01 -07002322 if (fi.name != null) {
2323 if (mAvailableFeatures.get(fi.name) == null) {
2324 Log.e(TAG, "Package " + pkg.packageName
2325 + " requires unavailable feature "
2326 + fi.name + "; failing!");
2327 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2328 return null;
2329 }
2330 }
2331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 }
2333 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 if (pkg.mSharedUserId != null) {
2336 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2337 pkg.applicationInfo.flags, true);
2338 if (suid == null) {
2339 Log.w(TAG, "Creating application package " + pkgName
2340 + " for shared user failed");
2341 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2342 return null;
2343 }
2344 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2345 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2346 + suid.userId + "): packages=" + suid.packages);
2347 }
2348 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002349
2350 // Just create the setting, don't add it yet. For already existing packages
2351 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2353 destResourceFile, pkg.applicationInfo.flags, true, false);
2354 if (pkgSetting == null) {
2355 Log.w(TAG, "Creating application package " + pkgName + " failed");
2356 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2357 return null;
2358 }
2359 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2360 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2361 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 pkg.applicationInfo.uid = pkgSetting.userId;
2364 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002365
2366 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002367 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2368 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2369 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2370 return null;
2371 }
2372 // The signature has changed, but this package is in the system
2373 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002374 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 // However... if this package is part of a shared user, but it
2376 // doesn't match the signature of the shared user, let's fail.
2377 // What this means is that you can't change the signatures
2378 // associated with an overall shared user, which doesn't seem all
2379 // that unreasonable.
2380 if (pkgSetting.sharedUser != null) {
2381 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2382 pkg.mSignatures, false)) {
2383 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2384 return null;
2385 }
2386 }
2387 removeExisting = true;
2388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002389
The Android Open Source Project10592532009-03-18 17:39:46 -07002390 // Verify that this new package doesn't have any content providers
2391 // that conflict with existing packages. Only do this if the
2392 // package isn't already installed, since we don't want to break
2393 // things that are installed.
2394 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2395 int N = pkg.providers.size();
2396 int i;
2397 for (i=0; i<N; i++) {
2398 PackageParser.Provider p = pkg.providers.get(i);
2399 String names[] = p.info.authority.split(";");
2400 for (int j = 0; j < names.length; j++) {
2401 if (mProviders.containsKey(names[j])) {
2402 PackageParser.Provider other = mProviders.get(names[j]);
2403 Log.w(TAG, "Can't install because provider name " + names[j] +
2404 " (in package " + pkg.applicationInfo.packageName +
2405 ") is already used by "
2406 + ((other != null && other.component != null)
2407 ? other.component.getPackageName() : "?"));
2408 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2409 return null;
2410 }
2411 }
2412 }
2413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 }
2415
2416 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002417 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002419 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002420 if (ret != 0) {
2421 String msg = "System package " + pkg.packageName
2422 + " could not have data directory erased after signature change.";
2423 reportSettingsProblem(Log.WARN, msg);
2424 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2425 return null;
2426 }
2427 }
2428 Log.w(TAG, "System package " + pkg.packageName
2429 + " signature changed: existing data removed.");
2430 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2431 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002433 long scanFileTime = scanFile.lastModified();
2434 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2435 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2436 pkg.applicationInfo.processName = fixProcessName(
2437 pkg.applicationInfo.packageName,
2438 pkg.applicationInfo.processName,
2439 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002440
2441 File dataPath;
2442 if (mPlatformPackage == pkg) {
2443 // The system package is special.
2444 dataPath = new File (Environment.getDataDirectory(), "system");
2445 pkg.applicationInfo.dataDir = dataPath.getPath();
2446 } else {
2447 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002448 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2449 if (useEncryptedFSDir) {
2450 dataPath = new File(mSecureAppDataDir, pkgName);
2451 } else {
2452 dataPath = new File(mAppDataDir, pkgName);
2453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 if (dataPath.exists()) {
2455 mOutPermissions[1] = 0;
2456 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2457 if (mOutPermissions[1] == pkg.applicationInfo.uid
2458 || !Process.supportsProcesses()) {
2459 pkg.applicationInfo.dataDir = dataPath.getPath();
2460 } else {
2461 boolean recovered = false;
2462 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2463 // If this is a system app, we can at least delete its
2464 // current data so the application will still work.
2465 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002466 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 if(ret >= 0) {
2468 // Old data gone!
2469 String msg = "System package " + pkg.packageName
2470 + " has changed from uid: "
2471 + mOutPermissions[1] + " to "
2472 + pkg.applicationInfo.uid + "; old data erased";
2473 reportSettingsProblem(Log.WARN, msg);
2474 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002477 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 pkg.applicationInfo.uid);
2479 if (ret == -1) {
2480 // Ack should not happen!
2481 msg = "System package " + pkg.packageName
2482 + " could not have data directory re-created after delete.";
2483 reportSettingsProblem(Log.WARN, msg);
2484 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2485 return null;
2486 }
2487 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 if (!recovered) {
2490 mHasSystemUidErrors = true;
2491 }
2492 }
2493 if (!recovered) {
2494 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2495 + pkg.applicationInfo.uid + "/fs_"
2496 + mOutPermissions[1];
2497 String msg = "Package " + pkg.packageName
2498 + " has mismatched uid: "
2499 + mOutPermissions[1] + " on disk, "
2500 + pkg.applicationInfo.uid + " in settings";
2501 synchronized (mPackages) {
2502 if (!mReportedUidError) {
2503 mReportedUidError = true;
2504 msg = msg + "; read messages:\n"
2505 + mSettings.getReadMessagesLP();
2506 }
2507 reportSettingsProblem(Log.ERROR, msg);
2508 }
2509 }
2510 }
2511 pkg.applicationInfo.dataDir = dataPath.getPath();
2512 } else {
2513 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2514 Log.v(TAG, "Want this data dir: " + dataPath);
2515 //invoke installer to do the actual installation
2516 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002517 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 pkg.applicationInfo.uid);
2519 if(ret < 0) {
2520 // Error from installer
2521 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2522 return null;
2523 }
2524 } else {
2525 dataPath.mkdirs();
2526 if (dataPath.exists()) {
2527 FileUtils.setPermissions(
2528 dataPath.toString(),
2529 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2530 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2531 }
2532 }
2533 if (dataPath.exists()) {
2534 pkg.applicationInfo.dataDir = dataPath.getPath();
2535 } else {
2536 Log.w(TAG, "Unable to create data directory: " + dataPath);
2537 pkg.applicationInfo.dataDir = null;
2538 }
2539 }
2540 }
2541
2542 // Perform shared library installation and dex validation and
2543 // optimization, if this is not a system app.
2544 if (mInstaller != null) {
2545 String path = scanFile.getPath();
2546 if (scanFileNewer) {
2547 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002548 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2549 if (err != PackageManager.INSTALL_SUCCEEDED) {
2550 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 return null;
2552 }
2553 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002554 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002555
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002556 if ((scanMode&SCAN_NO_DEX) == 0) {
2557 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2559 return null;
2560 }
2561 }
2562 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002564 if (mFactoryTest && pkg.requestedPermissions.contains(
2565 android.Manifest.permission.FACTORY_TEST)) {
2566 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2567 }
2568
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002569 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 if ((scanMode&SCAN_MONITOR) != 0) {
2571 pkg.mPath = destCodeFile.getAbsolutePath();
2572 mAppDirs.put(pkg.mPath, pkg);
2573 }
2574
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002575 // Request the ActivityManager to kill the process(only for existing packages)
2576 // so that we do not end up in a confused state while the user is still using the older
2577 // version of the application while the new one gets installed.
2578 IActivityManager am = ActivityManagerNative.getDefault();
2579 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2580 try {
2581 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2582 pkg.applicationInfo.uid);
2583 } catch (RemoteException e) {
2584 }
2585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002588 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002590 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002591 int N = pkg.providers.size();
2592 StringBuilder r = null;
2593 int i;
2594 for (i=0; i<N; i++) {
2595 PackageParser.Provider p = pkg.providers.get(i);
2596 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2597 p.info.processName, pkg.applicationInfo.uid);
2598 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2599 p.info.name), p);
2600 p.syncable = p.info.isSyncable;
2601 String names[] = p.info.authority.split(";");
2602 p.info.authority = null;
2603 for (int j = 0; j < names.length; j++) {
2604 if (j == 1 && p.syncable) {
2605 // We only want the first authority for a provider to possibly be
2606 // syncable, so if we already added this provider using a different
2607 // authority clear the syncable flag. We copy the provider before
2608 // changing it because the mProviders object contains a reference
2609 // to a provider that we don't want to change.
2610 // Only do this for the second authority since the resulting provider
2611 // object can be the same for all future authorities for this provider.
2612 p = new PackageParser.Provider(p);
2613 p.syncable = false;
2614 }
2615 if (!mProviders.containsKey(names[j])) {
2616 mProviders.put(names[j], p);
2617 if (p.info.authority == null) {
2618 p.info.authority = names[j];
2619 } else {
2620 p.info.authority = p.info.authority + ";" + names[j];
2621 }
2622 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2623 Log.d(TAG, "Registered content provider: " + names[j] +
2624 ", className = " + p.info.name +
2625 ", isSyncable = " + p.info.isSyncable);
2626 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002627 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 Log.w(TAG, "Skipping provider name " + names[j] +
2629 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002630 "): name already used by "
2631 + ((other != null && other.component != null)
2632 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002633 }
2634 }
2635 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2636 if (r == null) {
2637 r = new StringBuilder(256);
2638 } else {
2639 r.append(' ');
2640 }
2641 r.append(p.info.name);
2642 }
2643 }
2644 if (r != null) {
2645 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2646 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 N = pkg.services.size();
2649 r = null;
2650 for (i=0; i<N; i++) {
2651 PackageParser.Service s = pkg.services.get(i);
2652 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2653 s.info.processName, pkg.applicationInfo.uid);
2654 mServices.addService(s);
2655 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2656 if (r == null) {
2657 r = new StringBuilder(256);
2658 } else {
2659 r.append(' ');
2660 }
2661 r.append(s.info.name);
2662 }
2663 }
2664 if (r != null) {
2665 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2666 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 N = pkg.receivers.size();
2669 r = null;
2670 for (i=0; i<N; i++) {
2671 PackageParser.Activity a = pkg.receivers.get(i);
2672 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2673 a.info.processName, pkg.applicationInfo.uid);
2674 mReceivers.addActivity(a, "receiver");
2675 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2676 if (r == null) {
2677 r = new StringBuilder(256);
2678 } else {
2679 r.append(' ');
2680 }
2681 r.append(a.info.name);
2682 }
2683 }
2684 if (r != null) {
2685 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2686 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 N = pkg.activities.size();
2689 r = null;
2690 for (i=0; i<N; i++) {
2691 PackageParser.Activity a = pkg.activities.get(i);
2692 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2693 a.info.processName, pkg.applicationInfo.uid);
2694 mActivities.addActivity(a, "activity");
2695 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2696 if (r == null) {
2697 r = new StringBuilder(256);
2698 } else {
2699 r.append(' ');
2700 }
2701 r.append(a.info.name);
2702 }
2703 }
2704 if (r != null) {
2705 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2706 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 N = pkg.permissionGroups.size();
2709 r = null;
2710 for (i=0; i<N; i++) {
2711 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2712 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2713 if (cur == null) {
2714 mPermissionGroups.put(pg.info.name, pg);
2715 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2716 if (r == null) {
2717 r = new StringBuilder(256);
2718 } else {
2719 r.append(' ');
2720 }
2721 r.append(pg.info.name);
2722 }
2723 } else {
2724 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2725 + pg.info.packageName + " ignored: original from "
2726 + cur.info.packageName);
2727 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2728 if (r == null) {
2729 r = new StringBuilder(256);
2730 } else {
2731 r.append(' ');
2732 }
2733 r.append("DUP:");
2734 r.append(pg.info.name);
2735 }
2736 }
2737 }
2738 if (r != null) {
2739 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2740 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 N = pkg.permissions.size();
2743 r = null;
2744 for (i=0; i<N; i++) {
2745 PackageParser.Permission p = pkg.permissions.get(i);
2746 HashMap<String, BasePermission> permissionMap =
2747 p.tree ? mSettings.mPermissionTrees
2748 : mSettings.mPermissions;
2749 p.group = mPermissionGroups.get(p.info.group);
2750 if (p.info.group == null || p.group != null) {
2751 BasePermission bp = permissionMap.get(p.info.name);
2752 if (bp == null) {
2753 bp = new BasePermission(p.info.name, p.info.packageName,
2754 BasePermission.TYPE_NORMAL);
2755 permissionMap.put(p.info.name, bp);
2756 }
2757 if (bp.perm == null) {
2758 if (bp.sourcePackage == null
2759 || bp.sourcePackage.equals(p.info.packageName)) {
2760 BasePermission tree = findPermissionTreeLP(p.info.name);
2761 if (tree == null
2762 || tree.sourcePackage.equals(p.info.packageName)) {
2763 bp.perm = p;
2764 bp.uid = pkg.applicationInfo.uid;
2765 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2766 if (r == null) {
2767 r = new StringBuilder(256);
2768 } else {
2769 r.append(' ');
2770 }
2771 r.append(p.info.name);
2772 }
2773 } else {
2774 Log.w(TAG, "Permission " + p.info.name + " from package "
2775 + p.info.packageName + " ignored: base tree "
2776 + tree.name + " is from package "
2777 + tree.sourcePackage);
2778 }
2779 } else {
2780 Log.w(TAG, "Permission " + p.info.name + " from package "
2781 + p.info.packageName + " ignored: original from "
2782 + bp.sourcePackage);
2783 }
2784 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2785 if (r == null) {
2786 r = new StringBuilder(256);
2787 } else {
2788 r.append(' ');
2789 }
2790 r.append("DUP:");
2791 r.append(p.info.name);
2792 }
2793 } else {
2794 Log.w(TAG, "Permission " + p.info.name + " from package "
2795 + p.info.packageName + " ignored: no group "
2796 + p.group);
2797 }
2798 }
2799 if (r != null) {
2800 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2801 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002803 N = pkg.instrumentation.size();
2804 r = null;
2805 for (i=0; i<N; i++) {
2806 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2807 a.info.packageName = pkg.applicationInfo.packageName;
2808 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2809 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2810 a.info.dataDir = pkg.applicationInfo.dataDir;
2811 mInstrumentation.put(a.component, a);
2812 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2813 if (r == null) {
2814 r = new StringBuilder(256);
2815 } else {
2816 r.append(' ');
2817 }
2818 r.append(a.info.name);
2819 }
2820 }
2821 if (r != null) {
2822 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2823 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002824
Dianne Hackborn854060af2009-07-09 18:14:31 -07002825 if (pkg.protectedBroadcasts != null) {
2826 N = pkg.protectedBroadcasts.size();
2827 for (i=0; i<N; i++) {
2828 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2829 }
2830 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002832 pkgSetting.setTimeStamp(scanFileTime);
2833 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 return pkg;
2836 }
2837
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002838 // The following constants are returned by cachePackageSharedLibsForAbiLI
2839 // to indicate if native shared libraries were found in the package.
2840 // Values are:
2841 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2842 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2843 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2844 // in package (and not installed)
2845 //
2846 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2847 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2848 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002849
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002850 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2851 // and automatically copy them to /data/data/<appname>/lib if present.
2852 //
2853 // NOTE: this method may throw an IOException if the library cannot
2854 // be copied to its final destination, e.g. if there isn't enough
2855 // room left on the data partition, or a ZipException if the package
2856 // file is malformed.
2857 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08002858 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
2859 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002860 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2861 final String apkLib = "lib/";
2862 final int apkLibLen = apkLib.length();
2863 final int cpuAbiLen = cpuAbi.length();
2864 final String libPrefix = "lib";
2865 final int libPrefixLen = libPrefix.length();
2866 final String libSuffix = ".so";
2867 final int libSuffixLen = libSuffix.length();
2868 boolean hasNativeLibraries = false;
2869 boolean installedNativeLibraries = false;
2870
2871 // the minimum length of a valid native shared library of the form
2872 // lib/<something>/lib<name>.so.
2873 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2874
2875 ZipFile zipFile = new ZipFile(scanFile);
2876 Enumeration<ZipEntry> entries =
2877 (Enumeration<ZipEntry>) zipFile.entries();
2878
2879 while (entries.hasMoreElements()) {
2880 ZipEntry entry = entries.nextElement();
2881 // skip directories
2882 if (entry.isDirectory()) {
2883 continue;
2884 }
2885 String entryName = entry.getName();
2886
2887 // check that the entry looks like lib/<something>/lib<name>.so
2888 // here, but don't check the ABI just yet.
2889 //
2890 // - must be sufficiently long
2891 // - must end with libSuffix, i.e. ".so"
2892 // - must start with apkLib, i.e. "lib/"
2893 if (entryName.length() < minEntryLen ||
2894 !entryName.endsWith(libSuffix) ||
2895 !entryName.startsWith(apkLib) ) {
2896 continue;
2897 }
2898
2899 // file name must start with libPrefix, i.e. "lib"
2900 int lastSlash = entryName.lastIndexOf('/');
2901
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002902 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002903 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2904 continue;
2905 }
2906
2907 hasNativeLibraries = true;
2908
2909 // check the cpuAbi now, between lib/ and /lib<name>.so
2910 //
2911 if (lastSlash != apkLibLen + cpuAbiLen ||
2912 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2913 continue;
2914
2915 // extract the library file name, ensure it doesn't contain
2916 // weird characters. we're guaranteed here that it doesn't contain
2917 // a directory separator though.
2918 String libFileName = entryName.substring(lastSlash+1);
2919 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2920 continue;
2921 }
2922
2923 installedNativeLibraries = true;
2924
2925 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2926 File.separator + libFileName;
2927 File sharedLibraryFile = new File(sharedLibraryFilePath);
2928 if (! sharedLibraryFile.exists() ||
2929 sharedLibraryFile.length() != entry.getSize() ||
2930 sharedLibraryFile.lastModified() != entry.getTime()) {
2931 if (Config.LOGD) {
2932 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002934 if (mInstaller == null) {
2935 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002936 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08002937 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002938 sharedLibraryFile);
2939 }
2940 }
2941 if (!hasNativeLibraries)
2942 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2943
2944 if (!installedNativeLibraries)
2945 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
2946
2947 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2948 }
2949
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08002950 // Find the gdbserver executable program in a package at
2951 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
2952 //
2953 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
2954 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
2955 //
2956 private int cachePackageGdbServerLI(PackageParser.Package pkg,
2957 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
2958 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
2959 final String GDBSERVER = "gdbserver";
2960 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
2961
2962 ZipFile zipFile = new ZipFile(scanFile);
2963 Enumeration<ZipEntry> entries =
2964 (Enumeration<ZipEntry>) zipFile.entries();
2965
2966 while (entries.hasMoreElements()) {
2967 ZipEntry entry = entries.nextElement();
2968 // skip directories
2969 if (entry.isDirectory()) {
2970 continue;
2971 }
2972 String entryName = entry.getName();
2973
2974 if (!entryName.equals(apkGdbServerPath)) {
2975 continue;
2976 }
2977
2978 String installGdbServerPath = installGdbServerDir.getPath() +
2979 "/" + GDBSERVER;
2980 File installGdbServerFile = new File(installGdbServerPath);
2981 if (! installGdbServerFile.exists() ||
2982 installGdbServerFile.length() != entry.getSize() ||
2983 installGdbServerFile.lastModified() != entry.getTime()) {
2984 if (Config.LOGD) {
2985 Log.d(TAG, "Caching gdbserver " + entry.getName());
2986 }
2987 if (mInstaller == null) {
2988 installGdbServerDir.mkdir();
2989 }
2990 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
2991 installGdbServerFile);
2992 }
2993 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2994 }
2995 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2996 }
2997
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002998 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
2999 // and copy them to /data/data/<appname>/lib.
3000 //
3001 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3002 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3003 // one if ro.product.cpu.abi2 is defined.
3004 //
3005 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3006 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003007 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003008 try {
3009 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3010
3011 // some architectures are capable of supporting several CPU ABIs
3012 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3013 // this is indicated by the definition of the ro.product.cpu.abi2
3014 // system property.
3015 //
3016 // only scan the package twice in case of ABI mismatch
3017 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003018 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003019 if (cpuAbi2 != null) {
3020 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003022
3023 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3024 Log.w(TAG,"Native ABI mismatch from package file");
3025 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003027
3028 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3029 cpuAbi = cpuAbi2;
3030 }
3031 }
3032
3033 // for debuggable packages, also extract gdbserver from lib/<abi>
3034 // into /data/data/<appname>/lib too.
3035 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3036 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3037 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3038 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3039 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003042 } catch (ZipException e) {
3043 Log.w(TAG, "Failed to extract data from package file", e);
3044 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003046 Log.w(TAG, "Failed to cache package shared libs", e);
3047 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003049 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 }
3051
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003052 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003054 File binaryDir,
3055 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 InputStream inputStream = zipFile.getInputStream(entry);
3057 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003058 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003060 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003061 // now need to be left as world readable and owned by the system.
3062 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3063 ! tempFile.setLastModified(entry.getTime()) ||
3064 FileUtils.setPermissions(tempFilePath,
3065 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003066 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003067 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003068 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 // Failed to properly write file.
3070 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003071 throw new IOException("Couldn't create cached binary "
3072 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 }
3074 } finally {
3075 inputStream.close();
3076 }
3077 }
3078
3079 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3080 if (chatty && Config.LOGD) Log.d(
3081 TAG, "Removing package " + pkg.applicationInfo.packageName );
3082
3083 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 mPackages.remove(pkg.applicationInfo.packageName);
3087 if (pkg.mPath != null) {
3088 mAppDirs.remove(pkg.mPath);
3089 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003091 PackageSetting ps = (PackageSetting)pkg.mExtras;
3092 if (ps != null && ps.sharedUser != null) {
3093 // XXX don't do this until the data is removed.
3094 if (false) {
3095 ps.sharedUser.packages.remove(ps);
3096 if (ps.sharedUser.packages.size() == 0) {
3097 // Remove.
3098 }
3099 }
3100 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 int N = pkg.providers.size();
3103 StringBuilder r = null;
3104 int i;
3105 for (i=0; i<N; i++) {
3106 PackageParser.Provider p = pkg.providers.get(i);
3107 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3108 p.info.name));
3109 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 /* The is another ContentProvider with this authority when
3112 * this app was installed so this authority is null,
3113 * Ignore it as we don't have to unregister the provider.
3114 */
3115 continue;
3116 }
3117 String names[] = p.info.authority.split(";");
3118 for (int j = 0; j < names.length; j++) {
3119 if (mProviders.get(names[j]) == p) {
3120 mProviders.remove(names[j]);
3121 if (chatty && Config.LOGD) Log.d(
3122 TAG, "Unregistered content provider: " + names[j] +
3123 ", className = " + p.info.name +
3124 ", isSyncable = " + p.info.isSyncable);
3125 }
3126 }
3127 if (chatty) {
3128 if (r == null) {
3129 r = new StringBuilder(256);
3130 } else {
3131 r.append(' ');
3132 }
3133 r.append(p.info.name);
3134 }
3135 }
3136 if (r != null) {
3137 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3138 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003140 N = pkg.services.size();
3141 r = null;
3142 for (i=0; i<N; i++) {
3143 PackageParser.Service s = pkg.services.get(i);
3144 mServices.removeService(s);
3145 if (chatty) {
3146 if (r == null) {
3147 r = new StringBuilder(256);
3148 } else {
3149 r.append(' ');
3150 }
3151 r.append(s.info.name);
3152 }
3153 }
3154 if (r != null) {
3155 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3156 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 N = pkg.receivers.size();
3159 r = null;
3160 for (i=0; i<N; i++) {
3161 PackageParser.Activity a = pkg.receivers.get(i);
3162 mReceivers.removeActivity(a, "receiver");
3163 if (chatty) {
3164 if (r == null) {
3165 r = new StringBuilder(256);
3166 } else {
3167 r.append(' ');
3168 }
3169 r.append(a.info.name);
3170 }
3171 }
3172 if (r != null) {
3173 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3174 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003176 N = pkg.activities.size();
3177 r = null;
3178 for (i=0; i<N; i++) {
3179 PackageParser.Activity a = pkg.activities.get(i);
3180 mActivities.removeActivity(a, "activity");
3181 if (chatty) {
3182 if (r == null) {
3183 r = new StringBuilder(256);
3184 } else {
3185 r.append(' ');
3186 }
3187 r.append(a.info.name);
3188 }
3189 }
3190 if (r != null) {
3191 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 N = pkg.permissions.size();
3195 r = null;
3196 for (i=0; i<N; i++) {
3197 PackageParser.Permission p = pkg.permissions.get(i);
3198 boolean tree = false;
3199 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3200 if (bp == null) {
3201 tree = true;
3202 bp = mSettings.mPermissionTrees.get(p.info.name);
3203 }
3204 if (bp != null && bp.perm == p) {
3205 if (bp.type != BasePermission.TYPE_BUILTIN) {
3206 if (tree) {
3207 mSettings.mPermissionTrees.remove(p.info.name);
3208 } else {
3209 mSettings.mPermissions.remove(p.info.name);
3210 }
3211 } else {
3212 bp.perm = null;
3213 }
3214 if (chatty) {
3215 if (r == null) {
3216 r = new StringBuilder(256);
3217 } else {
3218 r.append(' ');
3219 }
3220 r.append(p.info.name);
3221 }
3222 }
3223 }
3224 if (r != null) {
3225 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003228 N = pkg.instrumentation.size();
3229 r = null;
3230 for (i=0; i<N; i++) {
3231 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3232 mInstrumentation.remove(a.component);
3233 if (chatty) {
3234 if (r == null) {
3235 r = new StringBuilder(256);
3236 } else {
3237 r.append(' ');
3238 }
3239 r.append(a.info.name);
3240 }
3241 }
3242 if (r != null) {
3243 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3244 }
3245 }
3246 }
3247
3248 private static final boolean isPackageFilename(String name) {
3249 return name != null && name.endsWith(".apk");
3250 }
3251
3252 private void updatePermissionsLP() {
3253 // Make sure there are no dangling permission trees.
3254 Iterator<BasePermission> it = mSettings.mPermissionTrees
3255 .values().iterator();
3256 while (it.hasNext()) {
3257 BasePermission bp = it.next();
3258 if (bp.perm == null) {
3259 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3260 + " from package " + bp.sourcePackage);
3261 it.remove();
3262 }
3263 }
3264
3265 // Make sure all dynamic permissions have been assigned to a package,
3266 // and make sure there are no dangling permissions.
3267 it = mSettings.mPermissions.values().iterator();
3268 while (it.hasNext()) {
3269 BasePermission bp = it.next();
3270 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3271 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3272 + bp.name + " pkg=" + bp.sourcePackage
3273 + " info=" + bp.pendingInfo);
3274 if (bp.perm == null && bp.pendingInfo != null) {
3275 BasePermission tree = findPermissionTreeLP(bp.name);
3276 if (tree != null) {
3277 bp.perm = new PackageParser.Permission(tree.perm.owner,
3278 new PermissionInfo(bp.pendingInfo));
3279 bp.perm.info.packageName = tree.perm.info.packageName;
3280 bp.perm.info.name = bp.name;
3281 bp.uid = tree.uid;
3282 }
3283 }
3284 }
3285 if (bp.perm == null) {
3286 Log.w(TAG, "Removing dangling permission: " + bp.name
3287 + " from package " + bp.sourcePackage);
3288 it.remove();
3289 }
3290 }
3291
3292 // Now update the permissions for all packages, in particular
3293 // replace the granted permissions of the system packages.
3294 for (PackageParser.Package pkg : mPackages.values()) {
3295 grantPermissionsLP(pkg, false);
3296 }
3297 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3300 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3301 if (ps == null) {
3302 return;
3303 }
3304 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3305 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 if (replace) {
3308 ps.permissionsFixed = false;
3309 if (gp == ps) {
3310 gp.grantedPermissions.clear();
3311 gp.gids = mGlobalGids;
3312 }
3313 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 if (gp.gids == null) {
3316 gp.gids = mGlobalGids;
3317 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 final int N = pkg.requestedPermissions.size();
3320 for (int i=0; i<N; i++) {
3321 String name = pkg.requestedPermissions.get(i);
3322 BasePermission bp = mSettings.mPermissions.get(name);
3323 PackageParser.Permission p = bp != null ? bp.perm : null;
3324 if (false) {
3325 if (gp != ps) {
3326 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3327 + ": " + p);
3328 }
3329 }
3330 if (p != null) {
3331 final String perm = p.info.name;
3332 boolean allowed;
3333 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3334 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3335 allowed = true;
3336 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3337 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003338 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003340 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 == PackageManager.SIGNATURE_MATCH);
3342 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3343 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3344 // For updated system applications, the signatureOrSystem permission
3345 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003346 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3348 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3349 if(sysPs.grantedPermissions.contains(perm)) {
3350 allowed = true;
3351 } else {
3352 allowed = false;
3353 }
3354 } else {
3355 allowed = true;
3356 }
3357 }
3358 }
3359 } else {
3360 allowed = false;
3361 }
3362 if (false) {
3363 if (gp != ps) {
3364 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3365 }
3366 }
3367 if (allowed) {
3368 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3369 && ps.permissionsFixed) {
3370 // If this is an existing, non-system package, then
3371 // we can't add any new permissions to it.
3372 if (!gp.loadedPermissions.contains(perm)) {
3373 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003374 // Except... if this is a permission that was added
3375 // to the platform (note: need to only do this when
3376 // updating the platform).
3377 final int NP = PackageParser.NEW_PERMISSIONS.length;
3378 for (int ip=0; ip<NP; ip++) {
3379 final PackageParser.NewPermissionInfo npi
3380 = PackageParser.NEW_PERMISSIONS[ip];
3381 if (npi.name.equals(perm)
3382 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3383 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003384 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003385 + pkg.packageName);
3386 break;
3387 }
3388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 }
3390 }
3391 if (allowed) {
3392 if (!gp.grantedPermissions.contains(perm)) {
3393 addedPermission = true;
3394 gp.grantedPermissions.add(perm);
3395 gp.gids = appendInts(gp.gids, bp.gids);
3396 }
3397 } else {
3398 Log.w(TAG, "Not granting permission " + perm
3399 + " to package " + pkg.packageName
3400 + " because it was previously installed without");
3401 }
3402 } else {
3403 Log.w(TAG, "Not granting permission " + perm
3404 + " to package " + pkg.packageName
3405 + " (protectionLevel=" + p.info.protectionLevel
3406 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3407 + ")");
3408 }
3409 } else {
3410 Log.w(TAG, "Unknown permission " + name
3411 + " in package " + pkg.packageName);
3412 }
3413 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003416 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3417 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003418 // This is the first that we have heard about this package, so the
3419 // permissions we have now selected are fixed until explicitly
3420 // changed.
3421 ps.permissionsFixed = true;
3422 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3423 }
3424 }
3425
3426 private final class ActivityIntentResolver
3427 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003428 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003430 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 }
3432
Mihai Preda074edef2009-05-18 17:13:31 +02003433 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003435 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3437 }
3438
Mihai Predaeae850c2009-05-13 10:13:48 +02003439 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3440 ArrayList<PackageParser.Activity> packageActivities) {
3441 if (packageActivities == null) {
3442 return null;
3443 }
3444 mFlags = flags;
3445 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3446 int N = packageActivities.size();
3447 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3448 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003449
3450 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003451 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003452 intentFilters = packageActivities.get(i).intents;
3453 if (intentFilters != null && intentFilters.size() > 0) {
3454 listCut.add(intentFilters);
3455 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003456 }
3457 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3458 }
3459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 public final void addActivity(PackageParser.Activity a, String type) {
3461 mActivities.put(a.component, a);
3462 if (SHOW_INFO || Config.LOGV) Log.v(
3463 TAG, " " + type + " " +
3464 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3465 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3466 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003467 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3469 if (SHOW_INFO || Config.LOGV) {
3470 Log.v(TAG, " IntentFilter:");
3471 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3472 }
3473 if (!intent.debugCheck()) {
3474 Log.w(TAG, "==> For Activity " + a.info.name);
3475 }
3476 addFilter(intent);
3477 }
3478 }
3479
3480 public final void removeActivity(PackageParser.Activity a, String type) {
3481 mActivities.remove(a.component);
3482 if (SHOW_INFO || Config.LOGV) Log.v(
3483 TAG, " " + type + " " +
3484 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3485 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3486 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003487 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003488 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3489 if (SHOW_INFO || Config.LOGV) {
3490 Log.v(TAG, " IntentFilter:");
3491 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3492 }
3493 removeFilter(intent);
3494 }
3495 }
3496
3497 @Override
3498 protected boolean allowFilterResult(
3499 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3500 ActivityInfo filterAi = filter.activity.info;
3501 for (int i=dest.size()-1; i>=0; i--) {
3502 ActivityInfo destAi = dest.get(i).activityInfo;
3503 if (destAi.name == filterAi.name
3504 && destAi.packageName == filterAi.packageName) {
3505 return false;
3506 }
3507 }
3508 return true;
3509 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 @Override
3512 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3513 int match) {
3514 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3515 return null;
3516 }
3517 final PackageParser.Activity activity = info.activity;
3518 if (mSafeMode && (activity.info.applicationInfo.flags
3519 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3520 return null;
3521 }
3522 final ResolveInfo res = new ResolveInfo();
3523 res.activityInfo = PackageParser.generateActivityInfo(activity,
3524 mFlags);
3525 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3526 res.filter = info;
3527 }
3528 res.priority = info.getPriority();
3529 res.preferredOrder = activity.owner.mPreferredOrder;
3530 //System.out.println("Result: " + res.activityInfo.className +
3531 // " = " + res.priority);
3532 res.match = match;
3533 res.isDefault = info.hasDefault;
3534 res.labelRes = info.labelRes;
3535 res.nonLocalizedLabel = info.nonLocalizedLabel;
3536 res.icon = info.icon;
3537 return res;
3538 }
3539
3540 @Override
3541 protected void sortResults(List<ResolveInfo> results) {
3542 Collections.sort(results, mResolvePrioritySorter);
3543 }
3544
3545 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003546 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003547 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003548 out.print(prefix); out.print(
3549 Integer.toHexString(System.identityHashCode(filter.activity)));
3550 out.print(' ');
3551 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 }
3553
3554// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3555// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3556// final List<ResolveInfo> retList = Lists.newArrayList();
3557// while (i.hasNext()) {
3558// final ResolveInfo resolveInfo = i.next();
3559// if (isEnabledLP(resolveInfo.activityInfo)) {
3560// retList.add(resolveInfo);
3561// }
3562// }
3563// return retList;
3564// }
3565
3566 // Keys are String (activity class name), values are Activity.
3567 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3568 = new HashMap<ComponentName, PackageParser.Activity>();
3569 private int mFlags;
3570 }
3571
3572 private final class ServiceIntentResolver
3573 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003574 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003575 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003576 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 }
3578
Mihai Preda074edef2009-05-18 17:13:31 +02003579 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003581 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3583 }
3584
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003585 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3586 ArrayList<PackageParser.Service> packageServices) {
3587 if (packageServices == null) {
3588 return null;
3589 }
3590 mFlags = flags;
3591 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3592 int N = packageServices.size();
3593 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3594 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3595
3596 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3597 for (int i = 0; i < N; ++i) {
3598 intentFilters = packageServices.get(i).intents;
3599 if (intentFilters != null && intentFilters.size() > 0) {
3600 listCut.add(intentFilters);
3601 }
3602 }
3603 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3604 }
3605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003606 public final void addService(PackageParser.Service s) {
3607 mServices.put(s.component, s);
3608 if (SHOW_INFO || Config.LOGV) Log.v(
3609 TAG, " " + (s.info.nonLocalizedLabel != null
3610 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3611 if (SHOW_INFO || Config.LOGV) Log.v(
3612 TAG, " Class=" + s.info.name);
3613 int NI = s.intents.size();
3614 int j;
3615 for (j=0; j<NI; j++) {
3616 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3617 if (SHOW_INFO || Config.LOGV) {
3618 Log.v(TAG, " IntentFilter:");
3619 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3620 }
3621 if (!intent.debugCheck()) {
3622 Log.w(TAG, "==> For Service " + s.info.name);
3623 }
3624 addFilter(intent);
3625 }
3626 }
3627
3628 public final void removeService(PackageParser.Service s) {
3629 mServices.remove(s.component);
3630 if (SHOW_INFO || Config.LOGV) Log.v(
3631 TAG, " " + (s.info.nonLocalizedLabel != null
3632 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3633 if (SHOW_INFO || Config.LOGV) Log.v(
3634 TAG, " Class=" + s.info.name);
3635 int NI = s.intents.size();
3636 int j;
3637 for (j=0; j<NI; j++) {
3638 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3639 if (SHOW_INFO || Config.LOGV) {
3640 Log.v(TAG, " IntentFilter:");
3641 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3642 }
3643 removeFilter(intent);
3644 }
3645 }
3646
3647 @Override
3648 protected boolean allowFilterResult(
3649 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3650 ServiceInfo filterSi = filter.service.info;
3651 for (int i=dest.size()-1; i>=0; i--) {
3652 ServiceInfo destAi = dest.get(i).serviceInfo;
3653 if (destAi.name == filterSi.name
3654 && destAi.packageName == filterSi.packageName) {
3655 return false;
3656 }
3657 }
3658 return true;
3659 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 @Override
3662 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3663 int match) {
3664 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3665 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3666 return null;
3667 }
3668 final PackageParser.Service service = info.service;
3669 if (mSafeMode && (service.info.applicationInfo.flags
3670 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3671 return null;
3672 }
3673 final ResolveInfo res = new ResolveInfo();
3674 res.serviceInfo = PackageParser.generateServiceInfo(service,
3675 mFlags);
3676 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3677 res.filter = filter;
3678 }
3679 res.priority = info.getPriority();
3680 res.preferredOrder = service.owner.mPreferredOrder;
3681 //System.out.println("Result: " + res.activityInfo.className +
3682 // " = " + res.priority);
3683 res.match = match;
3684 res.isDefault = info.hasDefault;
3685 res.labelRes = info.labelRes;
3686 res.nonLocalizedLabel = info.nonLocalizedLabel;
3687 res.icon = info.icon;
3688 return res;
3689 }
3690
3691 @Override
3692 protected void sortResults(List<ResolveInfo> results) {
3693 Collections.sort(results, mResolvePrioritySorter);
3694 }
3695
3696 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003697 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003698 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003699 out.print(prefix); out.print(
3700 Integer.toHexString(System.identityHashCode(filter.service)));
3701 out.print(' ');
3702 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 }
3704
3705// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3706// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3707// final List<ResolveInfo> retList = Lists.newArrayList();
3708// while (i.hasNext()) {
3709// final ResolveInfo resolveInfo = (ResolveInfo) i;
3710// if (isEnabledLP(resolveInfo.serviceInfo)) {
3711// retList.add(resolveInfo);
3712// }
3713// }
3714// return retList;
3715// }
3716
3717 // Keys are String (activity class name), values are Activity.
3718 private final HashMap<ComponentName, PackageParser.Service> mServices
3719 = new HashMap<ComponentName, PackageParser.Service>();
3720 private int mFlags;
3721 };
3722
3723 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3724 new Comparator<ResolveInfo>() {
3725 public int compare(ResolveInfo r1, ResolveInfo r2) {
3726 int v1 = r1.priority;
3727 int v2 = r2.priority;
3728 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3729 if (v1 != v2) {
3730 return (v1 > v2) ? -1 : 1;
3731 }
3732 v1 = r1.preferredOrder;
3733 v2 = r2.preferredOrder;
3734 if (v1 != v2) {
3735 return (v1 > v2) ? -1 : 1;
3736 }
3737 if (r1.isDefault != r2.isDefault) {
3738 return r1.isDefault ? -1 : 1;
3739 }
3740 v1 = r1.match;
3741 v2 = r2.match;
3742 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3743 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3744 }
3745 };
3746
3747 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3748 new Comparator<ProviderInfo>() {
3749 public int compare(ProviderInfo p1, ProviderInfo p2) {
3750 final int v1 = p1.initOrder;
3751 final int v2 = p2.initOrder;
3752 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3753 }
3754 };
3755
3756 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3757 IActivityManager am = ActivityManagerNative.getDefault();
3758 if (am != null) {
3759 try {
3760 final Intent intent = new Intent(action,
3761 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3762 if (extras != null) {
3763 intent.putExtras(extras);
3764 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003765 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 am.broadcastIntent(
3767 null, intent,
3768 null, null, 0, null, null, null, false, false);
3769 } catch (RemoteException ex) {
3770 }
3771 }
3772 }
3773
3774 private final class AppDirObserver extends FileObserver {
3775 public AppDirObserver(String path, int mask, boolean isrom) {
3776 super(path, mask);
3777 mRootDir = path;
3778 mIsRom = isrom;
3779 }
3780
3781 public void onEvent(int event, String path) {
3782 String removedPackage = null;
3783 int removedUid = -1;
3784 String addedPackage = null;
3785 int addedUid = -1;
3786
3787 synchronized (mInstallLock) {
3788 String fullPathStr = null;
3789 File fullPath = null;
3790 if (path != null) {
3791 fullPath = new File(mRootDir, path);
3792 fullPathStr = fullPath.getPath();
3793 }
3794
3795 if (Config.LOGV) Log.v(
3796 TAG, "File " + fullPathStr + " changed: "
3797 + Integer.toHexString(event));
3798
3799 if (!isPackageFilename(path)) {
3800 if (Config.LOGV) Log.v(
3801 TAG, "Ignoring change of non-package file: " + fullPathStr);
3802 return;
3803 }
3804
3805 if ((event&REMOVE_EVENTS) != 0) {
3806 synchronized (mInstallLock) {
3807 PackageParser.Package p = mAppDirs.get(fullPathStr);
3808 if (p != null) {
3809 removePackageLI(p, true);
3810 removedPackage = p.applicationInfo.packageName;
3811 removedUid = p.applicationInfo.uid;
3812 }
3813 }
3814 }
3815
3816 if ((event&ADD_EVENTS) != 0) {
3817 PackageParser.Package p = mAppDirs.get(fullPathStr);
3818 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003819 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3821 PackageParser.PARSE_CHATTY |
3822 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08003823 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 if (p != null) {
3825 synchronized (mPackages) {
3826 grantPermissionsLP(p, false);
3827 }
3828 addedPackage = p.applicationInfo.packageName;
3829 addedUid = p.applicationInfo.uid;
3830 }
3831 }
3832 }
3833
3834 synchronized (mPackages) {
3835 mSettings.writeLP();
3836 }
3837 }
3838
3839 if (removedPackage != null) {
3840 Bundle extras = new Bundle(1);
3841 extras.putInt(Intent.EXTRA_UID, removedUid);
3842 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3843 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3844 }
3845 if (addedPackage != null) {
3846 Bundle extras = new Bundle(1);
3847 extras.putInt(Intent.EXTRA_UID, addedUid);
3848 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3849 }
3850 }
3851
3852 private final String mRootDir;
3853 private final boolean mIsRom;
3854 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 /* Called when a downloaded package installation has been confirmed by the user */
3857 public void installPackage(
3858 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003859 installPackage(packageURI, observer, flags, null);
3860 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003861
Jacek Surazski65e13172009-04-28 15:26:38 +02003862 /* Called when a downloaded package installation has been confirmed by the user */
3863 public void installPackage(
3864 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3865 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 mContext.enforceCallingOrSelfPermission(
3867 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003869 // Queue up an async operation since the package installation may take a little while.
3870 mHandler.post(new Runnable() {
3871 public void run() {
3872 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003873 // Result object to be returned
3874 PackageInstalledInfo res = new PackageInstalledInfo();
3875 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3876 res.uid = -1;
3877 res.pkg = null;
3878 res.removedInfo = new PackageRemovedInfo();
3879 // Make a temporary copy of file from given packageURI
3880 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3881 if (tmpPackageFile != null) {
3882 synchronized (mInstallLock) {
3883 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 }
3886 if (observer != null) {
3887 try {
3888 observer.packageInstalled(res.name, res.returnCode);
3889 } catch (RemoteException e) {
3890 Log.i(TAG, "Observer no longer exists.");
3891 }
3892 }
3893 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3894 // call appears in the synchronized block above.
3895 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3896 res.removedInfo.sendBroadcast(false, true);
3897 Bundle extras = new Bundle(1);
3898 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003899 final boolean update = res.removedInfo.removedPackage != null;
3900 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3902 }
3903 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3904 res.pkg.applicationInfo.packageName,
3905 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003906 if (update) {
3907 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3908 res.pkg.applicationInfo.packageName,
3909 extras);
3910 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003911 }
3912 Runtime.getRuntime().gc();
3913 }
3914 });
3915 }
3916
3917 class PackageInstalledInfo {
3918 String name;
3919 int uid;
3920 PackageParser.Package pkg;
3921 int returnCode;
3922 PackageRemovedInfo removedInfo;
3923 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 /*
3926 * Install a non-existing package.
3927 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003928 private void installNewPackageLI(PackageParser.Package pkg,
3929 int parseFlags,
3930 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02003931 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08003933 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003934 String pkgName = pkg.packageName;
3935 boolean onSd = (parseFlags & PackageParser.PARSE_ON_SDCARD) != 0;
Oscar Montemayora8529f62009-11-18 10:14:20 -08003936
3937 if (useEncryptedFilesystemForPackage(pkg)) {
3938 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
3939 } else {
3940 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 res.name = pkgName;
3943 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003944 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003946 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003947 + " without first uninstalling.");
3948 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3949 return;
3950 }
3951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003952 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003953 if (onSd) {
3954 // Create secure container mount point for package
3955 String cPath = createSdDir(new File(pkg.mScanPath), pkgName);
3956 if (cPath == null) {
3957 mLastScanError = res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
3958 return;
3959 }
3960 }
3961 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003962 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003963 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003964 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3965 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3966 }
3967 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003968 File destPackageFile = new File(pkg.mPath);
3969 if (destPackageFile.exists()) {
3970 // It's safe to do this because we know (from the above check) that the file
3971 // isn't currently used for an installed package.
3972 destPackageFile.delete();
3973 }
3974 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02003975 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 res);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003977 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3978 // Check if container can be finalized
3979 if(onSd && !finalizeSdDir(pkgName)) {
3980 res.returnCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
3981 }
3982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 // delete the partially installed application. the data directory will have to be
3984 // restored if it was already existing
3985 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3986 // remove package from internal structures. Note that we want deletePackageX to
3987 // delete the package data and cache directories that it created in
3988 // scanPackageLocked, unless those directories existed before we even tried to
3989 // install.
3990 deletePackageLI(
3991 pkgName, true,
3992 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3993 res.removedInfo);
3994 }
3995 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003996 if (onSd && res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3997 // Destroy cache
3998 destroySdDir(pkgName);
3999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004000 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004001
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004002 private void replacePackageLI(PackageParser.Package pkg,
4003 int parseFlags,
4004 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004005 String installerPackageName, PackageInstalledInfo res) {
4006
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004007 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004008 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004009 // First find the old package info and check signatures
4010 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004011 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004012 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
4013 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4015 return;
4016 }
4017 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004018 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 if(sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004020 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004021 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004022 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 }
4024 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004027 PackageParser.Package pkg,
4028 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004029 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 PackageParser.Package newPackage = null;
4031 String pkgName = deletedPackage.packageName;
4032 boolean deletedPkg = true;
4033 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004034
Jacek Surazski65e13172009-04-28 15:26:38 +02004035 String oldInstallerPackageName = null;
4036 synchronized (mPackages) {
4037 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
4038 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004039
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004040 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 // First delete the existing package while retaining the data directory
4042 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
4043 res.removedInfo)) {
4044 // If the existing package was'nt successfully deleted
4045 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4046 deletedPkg = false;
4047 } else {
4048 // Successfully deleted the old package. Now proceed with re-installation
4049 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004050 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004051 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004052 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4054 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08004055 }
4056 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004057 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004058 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 res);
4060 updatedSettings = true;
4061 }
4062 }
4063
4064 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4065 // If we deleted an exisiting package, the old source and resource files that we
4066 // were keeping around in case we needed them (see below) can now be deleted
4067 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
4068 final ApplicationInfo installedPackageAppInfo =
4069 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004070 deletePackageResourcesLI(pkgName,
4071 !deletedPackageAppInfo.sourceDir
4072 .equals(installedPackageAppInfo.sourceDir)
4073 ? deletedPackageAppInfo.sourceDir : null,
4074 !deletedPackageAppInfo.publicSourceDir
4075 .equals(installedPackageAppInfo.publicSourceDir)
4076 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 //update signature on the new package setting
4078 //this should always succeed, since we checked the
4079 //signature earlier.
4080 synchronized(mPackages) {
4081 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4082 parseFlags, true);
4083 }
4084 } else {
4085 // remove package from internal structures. Note that we want deletePackageX to
4086 // delete the package data and cache directories that it created in
4087 // scanPackageLocked, unless those directories existed before we even tried to
4088 // install.
4089 if(updatedSettings) {
4090 deletePackageLI(
4091 pkgName, true,
4092 PackageManager.DONT_DELETE_DATA,
4093 res.removedInfo);
4094 }
4095 // Since we failed to install the new package we need to restore the old
4096 // package that we deleted.
4097 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004098 File restoreFile = new File(deletedPackage.mPath);
4099 if (restoreFile == null) {
4100 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4101 return;
4102 }
4103 File restoreTmpFile = createTempPackageFile();
4104 if (restoreTmpFile == null) {
4105 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
4106 return;
4107 }
4108 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
4109 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
4110 return;
4111 }
4112 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4113 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004115 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004117 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004118 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
4119 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4120 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4121 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004122 }
4123 }
4124 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004127 PackageParser.Package pkg,
4128 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004129 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 PackageParser.Package newPackage = null;
4131 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004132 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004133 PackageParser.PARSE_IS_SYSTEM;
4134 String packageName = deletedPackage.packageName;
4135 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4136 if (packageName == null) {
4137 Log.w(TAG, "Attempt to delete null packageName.");
4138 return;
4139 }
4140 PackageParser.Package oldPkg;
4141 PackageSetting oldPkgSetting;
4142 synchronized (mPackages) {
4143 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004144 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004145 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4146 (oldPkgSetting == null)) {
4147 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4148 return;
4149 }
4150 }
4151 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4152 res.removedInfo.removedPackage = packageName;
4153 // Remove existing system package
4154 removePackageLI(oldPkg, true);
4155 synchronized (mPackages) {
4156 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4157 }
4158
4159 // Successfully disabled the old package. Now proceed with re-installation
4160 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4161 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004162 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004164 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004165 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4166 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4167 }
4168 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004169 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 updatedSettings = true;
4171 }
4172
4173 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4174 //update signature on the new package setting
4175 //this should always succeed, since we checked the
4176 //signature earlier.
4177 synchronized(mPackages) {
4178 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4179 parseFlags, true);
4180 }
4181 } else {
4182 // Re installation failed. Restore old information
4183 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004184 if (newPackage != null) {
4185 removePackageLI(newPackage, true);
4186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004187 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004188 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004190 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004191 // Restore the old system information in Settings
4192 synchronized(mPackages) {
4193 if(updatedSettings) {
4194 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004195 mSettings.setInstallerPackageName(packageName,
4196 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 }
4198 mSettings.writeLP();
4199 }
4200 }
4201 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004202
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004203 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004204 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004205 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 synchronized (mPackages) {
4207 //write settings. the installStatus will be incomplete at this stage.
4208 //note that the new package setting would have already been
4209 //added to mPackages. It hasn't been persisted yet.
4210 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4211 mSettings.writeLP();
4212 }
4213
4214 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004215 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4216 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004217 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004218 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004219 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4220 return;
4221 }
4222 }
4223 // XXX There are probably some big issues here: upon doing
4224 // the rename, we have reached the point of no return (the
4225 // original .apk is gone!), so we can't fail. Yet... we can.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004226 File scanFile = new File(newPackage.mScanPath);
4227 if (!scanFile.renameTo(new File(newPackage.mPath))) {
4228 Log.e(TAG, "Couldn't move package file: " + newPackage.mScanPath + " to: " + newPackage.mPath);
4229 // TODO rename should work. Workaround
4230 if (!FileUtils.copyFile(scanFile, new File(newPackage.mPath))) {
4231 Log.e(TAG, "Couldn't move package file to: " + newPackage.mPath);
4232 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004235 res.returnCode = setPermissionsLI(newPackage);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4237 return;
4238 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004239 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004240 }
4241 }
4242 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4243 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004244 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 }
4246 }
4247
4248 synchronized (mPackages) {
4249 grantPermissionsLP(newPackage, true);
4250 res.name = pkgName;
4251 res.uid = newPackage.applicationInfo.uid;
4252 res.pkg = newPackage;
4253 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004254 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004255 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4256 //to update install status
4257 mSettings.writeLP();
4258 }
4259 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004260
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004261 private File copyTempInstallFile(Uri pPackageURI,
4262 PackageInstalledInfo res) {
4263 File tmpPackageFile = createTempPackageFile();
4264 int retCode = PackageManager.INSTALL_SUCCEEDED;
4265 if (tmpPackageFile == null) {
4266 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4267 return null;
4268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004269
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004270 if (pPackageURI.getScheme().equals("file")) {
4271 final File srcPackageFile = new File(pPackageURI.getPath());
4272 // We copy the source package file to a temp file and then rename it to the
4273 // destination file in order to eliminate a window where the package directory
4274 // scanner notices the new package file but it's not completely copied yet.
4275 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4276 Log.e(TAG, "Couldn't copy package file to temp file.");
4277 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004279 } else if (pPackageURI.getScheme().equals("content")) {
4280 ParcelFileDescriptor fd = null;
4281 try {
4282 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4283 } catch (FileNotFoundException e) {
4284 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4285 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4286 }
4287 if (fd == null) {
4288 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4289 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4290 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004291 if (Config.LOGV) {
4292 Log.v(TAG, "Opened file descriptor from download service.");
4293 }
4294 ParcelFileDescriptor.AutoCloseInputStream
4295 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4296 // We copy the source package file to a temp file and then rename it to the
4297 // destination file in order to eliminate a window where the package directory
4298 // scanner notices the new package file but it's not completely copied yet.
4299 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4300 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004301 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004304 } else {
4305 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4306 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4307 }
4308
4309 res.returnCode = retCode;
4310 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4311 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4312 tmpPackageFile.delete();
4313 }
4314 return null;
4315 }
4316 return tmpPackageFile;
4317 }
4318
4319 private void installPackageLI(Uri pPackageURI,
4320 int pFlags, boolean newInstall, String installerPackageName,
4321 File tmpPackageFile, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004322 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
4323 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004324 boolean replacingExistingPackage = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004325 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
4326 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004327 // Result object to be returned
4328 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4329
4330 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004331 // Retrieve PackageSettings and parse package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004332 int parseFlags = PackageParser.PARSE_CHATTY |
4333 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
4334 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 parseFlags |= mDefParseFlags;
4336 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4337 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004338 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004339 null, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 if (pkg == null) {
4341 res.returnCode = pp.getParseError();
4342 break main_flow;
4343 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004344 String pkgName = res.name = pkg.packageName;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004345 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4346 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4347 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4348 break main_flow;
4349 }
4350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4352 res.returnCode = pp.getParseError();
4353 break main_flow;
4354 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 synchronized (mPackages) {
4357 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004358 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 && mPackages.containsKey(pkgName)) {
4360 replacingExistingPackage = true;
4361 }
4362 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 if(replacingExistingPackage) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004365 replacePackageLI(pkg, parseFlags, scanMode,
4366 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004368 installNewPackageLI(pkg, parseFlags, scanMode,
4369 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 }
4371 } finally {
4372 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4373 tmpPackageFile.delete();
4374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 }
4376 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004377
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004378 private int setPermissionsLI(PackageParser.Package newPackage) {
4379 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 int retCode;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004381 if ((newPackage.applicationInfo.flags
4382 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
4383 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 try {
4385 extractPublicFiles(newPackage, destResourceFile);
4386 } catch (IOException e) {
4387 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4388 " forward-locked app.");
4389 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4390 } finally {
4391 //TODO clean up the extracted public files
4392 }
4393 if (mInstaller != null) {
4394 retCode = mInstaller.setForwardLockPerm(pkgName,
4395 newPackage.applicationInfo.uid);
4396 } else {
4397 final int filePermissions =
4398 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004399 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 newPackage.applicationInfo.uid);
4401 }
4402 } else {
4403 final int filePermissions =
4404 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4405 |FileUtils.S_IROTH;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004406 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 }
4408 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004409 Log.e(TAG, "Couldn't set new package file permissions for " +
4410 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 + ". The return code was: " + retCode);
4412 }
4413 return PackageManager.INSTALL_SUCCEEDED;
4414 }
4415
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004416 private boolean isForwardLocked(PackageParser.Package pkg) {
4417 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004418 }
4419
4420 private void extractPublicFiles(PackageParser.Package newPackage,
4421 File publicZipFile) throws IOException {
4422 final ZipOutputStream publicZipOutStream =
4423 new ZipOutputStream(new FileOutputStream(publicZipFile));
4424 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4425
4426 // Copy manifest, resources.arsc and res directory to public zip
4427
4428 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4429 while (privateZipEntries.hasMoreElements()) {
4430 final ZipEntry zipEntry = privateZipEntries.nextElement();
4431 final String zipEntryName = zipEntry.getName();
4432 if ("AndroidManifest.xml".equals(zipEntryName)
4433 || "resources.arsc".equals(zipEntryName)
4434 || zipEntryName.startsWith("res/")) {
4435 try {
4436 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4437 } catch (IOException e) {
4438 try {
4439 publicZipOutStream.close();
4440 throw e;
4441 } finally {
4442 publicZipFile.delete();
4443 }
4444 }
4445 }
4446 }
4447
4448 publicZipOutStream.close();
4449 FileUtils.setPermissions(
4450 publicZipFile.getAbsolutePath(),
4451 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4452 -1, -1);
4453 }
4454
4455 private static void copyZipEntry(ZipEntry zipEntry,
4456 ZipFile inZipFile,
4457 ZipOutputStream outZipStream) throws IOException {
4458 byte[] buffer = new byte[4096];
4459 int num;
4460
4461 ZipEntry newEntry;
4462 if (zipEntry.getMethod() == ZipEntry.STORED) {
4463 // Preserve the STORED method of the input entry.
4464 newEntry = new ZipEntry(zipEntry);
4465 } else {
4466 // Create a new entry so that the compressed len is recomputed.
4467 newEntry = new ZipEntry(zipEntry.getName());
4468 }
4469 outZipStream.putNextEntry(newEntry);
4470
4471 InputStream data = inZipFile.getInputStream(zipEntry);
4472 while ((num = data.read(buffer)) > 0) {
4473 outZipStream.write(buffer, 0, num);
4474 }
4475 outZipStream.flush();
4476 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 private void deleteTempPackageFiles() {
4479 FilenameFilter filter = new FilenameFilter() {
4480 public boolean accept(File dir, String name) {
4481 return name.startsWith("vmdl") && name.endsWith(".tmp");
4482 }
4483 };
4484 String tmpFilesList[] = mAppInstallDir.list(filter);
4485 if(tmpFilesList == null) {
4486 return;
4487 }
4488 for(int i = 0; i < tmpFilesList.length; i++) {
4489 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4490 tmpFile.delete();
4491 }
4492 }
4493
4494 private File createTempPackageFile() {
4495 File tmpPackageFile;
4496 try {
4497 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4498 } catch (IOException e) {
4499 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4500 return null;
4501 }
4502 try {
4503 FileUtils.setPermissions(
4504 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4505 -1, -1);
4506 } catch (IOException e) {
4507 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4508 return null;
4509 }
4510 return tmpPackageFile;
4511 }
4512
4513 public void deletePackage(final String packageName,
4514 final IPackageDeleteObserver observer,
4515 final int flags) {
4516 mContext.enforceCallingOrSelfPermission(
4517 android.Manifest.permission.DELETE_PACKAGES, null);
4518 // Queue up an async operation since the package deletion may take a little while.
4519 mHandler.post(new Runnable() {
4520 public void run() {
4521 mHandler.removeCallbacks(this);
4522 final boolean succeded = deletePackageX(packageName, true, true, flags);
4523 if (observer != null) {
4524 try {
4525 observer.packageDeleted(succeded);
4526 } catch (RemoteException e) {
4527 Log.i(TAG, "Observer no longer exists.");
4528 } //end catch
4529 } //end if
4530 } //end run
4531 });
4532 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 /**
4535 * This method is an internal method that could be get invoked either
4536 * to delete an installed package or to clean up a failed installation.
4537 * After deleting an installed package, a broadcast is sent to notify any
4538 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004539 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004540 * installation wouldn't have sent the initial broadcast either
4541 * The key steps in deleting a package are
4542 * deleting the package information in internal structures like mPackages,
4543 * deleting the packages base directories through installd
4544 * updating mSettings to reflect current status
4545 * persisting settings for later use
4546 * sending a broadcast if necessary
4547 */
4548
4549 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4550 boolean deleteCodeAndResources, int flags) {
4551 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004552 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004553
4554 synchronized (mInstallLock) {
4555 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004559 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4560 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4561
4562 // If the removed package was a system update, the old system packaged
4563 // was re-enabled; we need to broadcast this information
4564 if (systemUpdate) {
4565 Bundle extras = new Bundle(1);
4566 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4567 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4568
4569 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4570 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573 return res;
4574 }
4575
4576 static class PackageRemovedInfo {
4577 String removedPackage;
4578 int uid = -1;
4579 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004580 boolean isRemovedPackageSystemUpdate = false;
4581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 void sendBroadcast(boolean fullRemove, boolean replacing) {
4583 Bundle extras = new Bundle(1);
4584 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4585 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4586 if (replacing) {
4587 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4588 }
4589 if (removedPackage != null) {
4590 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4591 }
4592 if (removedUid >= 0) {
4593 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4594 }
4595 }
4596 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 /*
4599 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4600 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004601 * 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 -08004602 * delete a partially installed application.
4603 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004604 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 int flags) {
4606 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004607 if (outInfo != null) {
4608 outInfo.removedPackage = packageName;
4609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004610 removePackageLI(p, true);
4611 // Retrieve object to delete permissions for shared user later on
4612 PackageSetting deletedPs;
4613 synchronized (mPackages) {
4614 deletedPs = mSettings.mPackages.get(packageName);
4615 }
4616 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004617 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004619 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 if (retCode < 0) {
4621 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4622 + packageName + ", retcode=" + retCode);
4623 // we don't consider this to be a failure of the core package deletion
4624 }
4625 } else {
4626 //for emulator
4627 PackageParser.Package pkg = mPackages.get(packageName);
4628 File dataDir = new File(pkg.applicationInfo.dataDir);
4629 dataDir.delete();
4630 }
4631 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004632 if (outInfo != null) {
4633 outInfo.removedUid = mSettings.removePackageLP(packageName);
4634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 }
4636 }
4637 synchronized (mPackages) {
4638 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4639 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004640 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 }
4642 // Save settings now
4643 mSettings.writeLP ();
4644 }
4645 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004647 /*
4648 * Tries to delete system package.
4649 */
4650 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004651 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 ApplicationInfo applicationInfo = p.applicationInfo;
4653 //applicable for non-partially installed applications only
4654 if (applicationInfo == null) {
4655 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4656 return false;
4657 }
4658 PackageSetting ps = null;
4659 // Confirm if the system package has been updated
4660 // An updated system app can be deleted. This will also have to restore
4661 // the system pkg from system partition
4662 synchronized (mPackages) {
4663 ps = mSettings.getDisabledSystemPkg(p.packageName);
4664 }
4665 if (ps == null) {
4666 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4667 return false;
4668 } else {
4669 Log.i(TAG, "Deleting system pkg from data partition");
4670 }
4671 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004672 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004673 boolean deleteCodeAndResources = false;
4674 if (ps.versionCode < p.mVersionCode) {
4675 // Delete code and resources for downgrades
4676 deleteCodeAndResources = true;
4677 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4678 flags &= ~PackageManager.DONT_DELETE_DATA;
4679 }
4680 } else {
4681 // Preserve data by setting flag
4682 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4683 flags |= PackageManager.DONT_DELETE_DATA;
4684 }
4685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004686 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4687 if (!ret) {
4688 return false;
4689 }
4690 synchronized (mPackages) {
4691 // Reinstate the old system package
4692 mSettings.enableSystemPackageLP(p.packageName);
4693 }
4694 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004695 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004697 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004699 if (newPkg == null) {
4700 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4701 return false;
4702 }
4703 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004704 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004705 mSettings.writeLP();
4706 }
4707 return true;
4708 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004709
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004710 private void deletePackageResourcesLI(String packageName,
4711 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004712 if (sourceDir != null) {
4713 File sourceFile = new File(sourceDir);
4714 if (!sourceFile.exists()) {
4715 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4716 }
4717 // Delete application's code and resources
4718 sourceFile.delete();
4719 if (mInstaller != null) {
4720 int retCode = mInstaller.rmdex(sourceFile.toString());
4721 if (retCode < 0) {
4722 Log.w(TAG, "Couldn't remove dex file for package: "
4723 + packageName + " at location "
4724 + sourceFile.toString() + ", retcode=" + retCode);
4725 // we don't consider this to be a failure of the core package deletion
4726 }
4727 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004728 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004729 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4730 final File publicSourceFile = new File(publicSourceDir);
4731 if (!publicSourceFile.exists()) {
4732 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4733 }
4734 if (publicSourceFile.exists()) {
4735 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004736 }
4737 }
4738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4741 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4742 ApplicationInfo applicationInfo = p.applicationInfo;
4743 if (applicationInfo == null) {
4744 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4745 return false;
4746 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004747 if (outInfo != null) {
4748 outInfo.uid = applicationInfo.uid;
4749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004750
4751 // Delete package data from internal structures and also remove data if flag is set
4752 removePackageDataLI(p, outInfo, flags);
4753
4754 // Delete application code and resources
4755 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004756 deletePackageResourcesLI(applicationInfo.packageName,
4757 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004758 }
4759 return true;
4760 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 /*
4763 * This method handles package deletion in general
4764 */
4765 private boolean deletePackageLI(String packageName,
4766 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4767 if (packageName == null) {
4768 Log.w(TAG, "Attempt to delete null packageName.");
4769 return false;
4770 }
4771 PackageParser.Package p;
4772 boolean dataOnly = false;
4773 synchronized (mPackages) {
4774 p = mPackages.get(packageName);
4775 if (p == null) {
4776 //this retrieves partially installed apps
4777 dataOnly = true;
4778 PackageSetting ps = mSettings.mPackages.get(packageName);
4779 if (ps == null) {
4780 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4781 return false;
4782 }
4783 p = ps.pkg;
4784 }
4785 }
4786 if (p == null) {
4787 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4788 return false;
4789 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 if (dataOnly) {
4792 // Delete application data first
4793 removePackageDataLI(p, outInfo, flags);
4794 return true;
4795 }
4796 // At this point the package should have ApplicationInfo associated with it
4797 if (p.applicationInfo == null) {
4798 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4799 return false;
4800 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004801 boolean onSd = (p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0;
4802 // Mount sd container if needed
4803 if (onSd) {
4804 // TODO Better error handling from MountService api later
4805 mountSdDir(p.packageName, Process.SYSTEM_UID) ;
4806 }
4807 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004808 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4809 Log.i(TAG, "Removing system package:"+p.packageName);
4810 // When an updated system application is deleted we delete the existing resources as well and
4811 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004812 ret = deleteSystemPackageLI(p, flags, outInfo);
4813 } else {
4814 Log.i(TAG, "Removing non-system package:"+p.packageName);
4815 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004817 if (ret && onSd) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08004818 if (deleteCodeAndResources) {
4819 // Post a delayed destroy on the container since there might
4820 // be active processes holding open file handles to package
4821 // resources which will get killed by the process killer when
4822 // destroying the container. This might even kill the current
4823 // process and crash the system. Delay the destroy a bit so
4824 // that the active processes get to handle the uninstall broadcasts.
4825 sendDelayedDestroySdDir(packageName);
4826 } else {
4827 // Just unmount the directory
4828 unMountSdDir(packageName);
4829 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004830 }
4831 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004832 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004834 public void clearApplicationUserData(final String packageName,
4835 final IPackageDataObserver observer) {
4836 mContext.enforceCallingOrSelfPermission(
4837 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4838 // Queue up an async operation since the package deletion may take a little while.
4839 mHandler.post(new Runnable() {
4840 public void run() {
4841 mHandler.removeCallbacks(this);
4842 final boolean succeeded;
4843 synchronized (mInstallLock) {
4844 succeeded = clearApplicationUserDataLI(packageName);
4845 }
4846 if (succeeded) {
4847 // invoke DeviceStorageMonitor's update method to clear any notifications
4848 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4849 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4850 if (dsm != null) {
4851 dsm.updateMemory();
4852 }
4853 }
4854 if(observer != null) {
4855 try {
4856 observer.onRemoveCompleted(packageName, succeeded);
4857 } catch (RemoteException e) {
4858 Log.i(TAG, "Observer no longer exists.");
4859 }
4860 } //end if observer
4861 } //end run
4862 });
4863 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004865 private boolean clearApplicationUserDataLI(String packageName) {
4866 if (packageName == null) {
4867 Log.w(TAG, "Attempt to delete null packageName.");
4868 return false;
4869 }
4870 PackageParser.Package p;
4871 boolean dataOnly = false;
4872 synchronized (mPackages) {
4873 p = mPackages.get(packageName);
4874 if(p == null) {
4875 dataOnly = true;
4876 PackageSetting ps = mSettings.mPackages.get(packageName);
4877 if((ps == null) || (ps.pkg == null)) {
4878 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4879 return false;
4880 }
4881 p = ps.pkg;
4882 }
4883 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004884 boolean useEncryptedFSDir = false;
4885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 if(!dataOnly) {
4887 //need to check this only for fully installed applications
4888 if (p == null) {
4889 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4890 return false;
4891 }
4892 final ApplicationInfo applicationInfo = p.applicationInfo;
4893 if (applicationInfo == null) {
4894 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4895 return false;
4896 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004897 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004898 }
4899 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004900 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004901 if (retCode < 0) {
4902 Log.w(TAG, "Couldn't remove cache files for package: "
4903 + packageName);
4904 return false;
4905 }
4906 }
4907 return true;
4908 }
4909
4910 public void deleteApplicationCacheFiles(final String packageName,
4911 final IPackageDataObserver observer) {
4912 mContext.enforceCallingOrSelfPermission(
4913 android.Manifest.permission.DELETE_CACHE_FILES, null);
4914 // Queue up an async operation since the package deletion may take a little while.
4915 mHandler.post(new Runnable() {
4916 public void run() {
4917 mHandler.removeCallbacks(this);
4918 final boolean succeded;
4919 synchronized (mInstallLock) {
4920 succeded = deleteApplicationCacheFilesLI(packageName);
4921 }
4922 if(observer != null) {
4923 try {
4924 observer.onRemoveCompleted(packageName, succeded);
4925 } catch (RemoteException e) {
4926 Log.i(TAG, "Observer no longer exists.");
4927 }
4928 } //end if observer
4929 } //end run
4930 });
4931 }
4932
4933 private boolean deleteApplicationCacheFilesLI(String packageName) {
4934 if (packageName == null) {
4935 Log.w(TAG, "Attempt to delete null packageName.");
4936 return false;
4937 }
4938 PackageParser.Package p;
4939 synchronized (mPackages) {
4940 p = mPackages.get(packageName);
4941 }
4942 if (p == null) {
4943 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4944 return false;
4945 }
4946 final ApplicationInfo applicationInfo = p.applicationInfo;
4947 if (applicationInfo == null) {
4948 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4949 return false;
4950 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004951 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004953 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004954 if (retCode < 0) {
4955 Log.w(TAG, "Couldn't remove cache files for package: "
4956 + packageName);
4957 return false;
4958 }
4959 }
4960 return true;
4961 }
4962
4963 public void getPackageSizeInfo(final String packageName,
4964 final IPackageStatsObserver observer) {
4965 mContext.enforceCallingOrSelfPermission(
4966 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4967 // Queue up an async operation since the package deletion may take a little while.
4968 mHandler.post(new Runnable() {
4969 public void run() {
4970 mHandler.removeCallbacks(this);
4971 PackageStats lStats = new PackageStats(packageName);
4972 final boolean succeded;
4973 synchronized (mInstallLock) {
4974 succeded = getPackageSizeInfoLI(packageName, lStats);
4975 }
4976 if(observer != null) {
4977 try {
4978 observer.onGetStatsCompleted(lStats, succeded);
4979 } catch (RemoteException e) {
4980 Log.i(TAG, "Observer no longer exists.");
4981 }
4982 } //end if observer
4983 } //end run
4984 });
4985 }
4986
4987 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4988 if (packageName == null) {
4989 Log.w(TAG, "Attempt to get size of null packageName.");
4990 return false;
4991 }
4992 PackageParser.Package p;
4993 boolean dataOnly = false;
4994 synchronized (mPackages) {
4995 p = mPackages.get(packageName);
4996 if(p == null) {
4997 dataOnly = true;
4998 PackageSetting ps = mSettings.mPackages.get(packageName);
4999 if((ps == null) || (ps.pkg == null)) {
5000 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5001 return false;
5002 }
5003 p = ps.pkg;
5004 }
5005 }
5006 String publicSrcDir = null;
5007 if(!dataOnly) {
5008 final ApplicationInfo applicationInfo = p.applicationInfo;
5009 if (applicationInfo == null) {
5010 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5011 return false;
5012 }
5013 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
5014 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005015 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 if (mInstaller != null) {
5017 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08005018 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 if (res < 0) {
5020 return false;
5021 } else {
5022 return true;
5023 }
5024 }
5025 return true;
5026 }
5027
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005029 public void addPackageToPreferred(String packageName) {
5030 mContext.enforceCallingOrSelfPermission(
5031 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005032 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005033 }
5034
5035 public void removePackageFromPreferred(String packageName) {
5036 mContext.enforceCallingOrSelfPermission(
5037 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005038 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 }
5040
5041 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005042 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005043 }
5044
5045 public void addPreferredActivity(IntentFilter filter, int match,
5046 ComponentName[] set, ComponentName activity) {
5047 mContext.enforceCallingOrSelfPermission(
5048 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5049
5050 synchronized (mPackages) {
5051 Log.i(TAG, "Adding preferred activity " + activity + ":");
5052 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5053 mSettings.mPreferredActivities.addFilter(
5054 new PreferredActivity(filter, match, set, activity));
5055 mSettings.writeLP();
5056 }
5057 }
5058
Satish Sampath8dbe6122009-06-02 23:35:54 +01005059 public void replacePreferredActivity(IntentFilter filter, int match,
5060 ComponentName[] set, ComponentName activity) {
5061 mContext.enforceCallingOrSelfPermission(
5062 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5063 if (filter.countActions() != 1) {
5064 throw new IllegalArgumentException(
5065 "replacePreferredActivity expects filter to have only 1 action.");
5066 }
5067 if (filter.countCategories() != 1) {
5068 throw new IllegalArgumentException(
5069 "replacePreferredActivity expects filter to have only 1 category.");
5070 }
5071 if (filter.countDataAuthorities() != 0
5072 || filter.countDataPaths() != 0
5073 || filter.countDataSchemes() != 0
5074 || filter.countDataTypes() != 0) {
5075 throw new IllegalArgumentException(
5076 "replacePreferredActivity expects filter to have no data authorities, " +
5077 "paths, schemes or types.");
5078 }
5079 synchronized (mPackages) {
5080 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5081 String action = filter.getAction(0);
5082 String category = filter.getCategory(0);
5083 while (it.hasNext()) {
5084 PreferredActivity pa = it.next();
5085 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5086 it.remove();
5087 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5088 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5089 }
5090 }
5091 addPreferredActivity(filter, match, set, activity);
5092 }
5093 }
5094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 public void clearPackagePreferredActivities(String packageName) {
5096 mContext.enforceCallingOrSelfPermission(
5097 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5098
5099 synchronized (mPackages) {
5100 if (clearPackagePreferredActivitiesLP(packageName)) {
5101 mSettings.writeLP();
5102 }
5103 }
5104 }
5105
5106 boolean clearPackagePreferredActivitiesLP(String packageName) {
5107 boolean changed = false;
5108 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5109 while (it.hasNext()) {
5110 PreferredActivity pa = it.next();
5111 if (pa.mActivity.getPackageName().equals(packageName)) {
5112 it.remove();
5113 changed = true;
5114 }
5115 }
5116 return changed;
5117 }
5118
5119 public int getPreferredActivities(List<IntentFilter> outFilters,
5120 List<ComponentName> outActivities, String packageName) {
5121
5122 int num = 0;
5123 synchronized (mPackages) {
5124 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5125 while (it.hasNext()) {
5126 PreferredActivity pa = it.next();
5127 if (packageName == null
5128 || pa.mActivity.getPackageName().equals(packageName)) {
5129 if (outFilters != null) {
5130 outFilters.add(new IntentFilter(pa));
5131 }
5132 if (outActivities != null) {
5133 outActivities.add(pa.mActivity);
5134 }
5135 }
5136 }
5137 }
5138
5139 return num;
5140 }
5141
5142 public void setApplicationEnabledSetting(String appPackageName,
5143 int newState, int flags) {
5144 setEnabledSetting(appPackageName, null, newState, flags);
5145 }
5146
5147 public void setComponentEnabledSetting(ComponentName componentName,
5148 int newState, int flags) {
5149 setEnabledSetting(componentName.getPackageName(),
5150 componentName.getClassName(), newState, flags);
5151 }
5152
5153 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005154 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005155 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5156 || newState == COMPONENT_ENABLED_STATE_ENABLED
5157 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5158 throw new IllegalArgumentException("Invalid new component state: "
5159 + newState);
5160 }
5161 PackageSetting pkgSetting;
5162 final int uid = Binder.getCallingUid();
5163 final int permission = mContext.checkCallingPermission(
5164 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5165 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005166 boolean sendNow = false;
5167 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005168 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005170 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005171 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005172 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005174 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005176 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 }
5178 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005179 "Unknown component: " + packageName
5180 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005181 }
5182 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5183 throw new SecurityException(
5184 "Permission Denial: attempt to change component state from pid="
5185 + Binder.getCallingPid()
5186 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5187 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005188 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005189 // We're dealing with an application/package level state change
5190 pkgSetting.enabled = newState;
5191 } else {
5192 // We're dealing with a component level state change
5193 switch (newState) {
5194 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005195 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005196 break;
5197 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005198 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005199 break;
5200 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005201 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005202 break;
5203 default:
5204 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005205 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 }
5207 }
5208 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005209 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005210 components = mPendingBroadcasts.get(packageName);
5211 boolean newPackage = components == null;
5212 if (newPackage) {
5213 components = new ArrayList<String>();
5214 }
5215 if (!components.contains(componentName)) {
5216 components.add(componentName);
5217 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005218 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5219 sendNow = true;
5220 // Purge entry from pending broadcast list if another one exists already
5221 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005222 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005223 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005224 if (newPackage) {
5225 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005226 }
5227 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5228 // Schedule a message
5229 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5230 }
5231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005234 long callingId = Binder.clearCallingIdentity();
5235 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005236 if (sendNow) {
5237 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005238 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 } finally {
5241 Binder.restoreCallingIdentity(callingId);
5242 }
5243 }
5244
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005245 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005246 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5247 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5248 + " components=" + componentNames);
5249 Bundle extras = new Bundle(4);
5250 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5251 String nameList[] = new String[componentNames.size()];
5252 componentNames.toArray(nameList);
5253 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005254 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5255 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005256 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005257 }
5258
Jacek Surazski65e13172009-04-28 15:26:38 +02005259 public String getInstallerPackageName(String packageName) {
5260 synchronized (mPackages) {
5261 PackageSetting pkg = mSettings.mPackages.get(packageName);
5262 if (pkg == null) {
5263 throw new IllegalArgumentException("Unknown package: " + packageName);
5264 }
5265 return pkg.installerPackageName;
5266 }
5267 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 public int getApplicationEnabledSetting(String appPackageName) {
5270 synchronized (mPackages) {
5271 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5272 if (pkg == null) {
5273 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5274 }
5275 return pkg.enabled;
5276 }
5277 }
5278
5279 public int getComponentEnabledSetting(ComponentName componentName) {
5280 synchronized (mPackages) {
5281 final String packageNameStr = componentName.getPackageName();
5282 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5283 if (pkg == null) {
5284 throw new IllegalArgumentException("Unknown component: " + componentName);
5285 }
5286 final String classNameStr = componentName.getClassName();
5287 return pkg.currentEnabledStateLP(classNameStr);
5288 }
5289 }
5290
5291 public void enterSafeMode() {
5292 if (!mSystemReady) {
5293 mSafeMode = true;
5294 }
5295 }
5296
5297 public void systemReady() {
5298 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005299
5300 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005301 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005302 mContext.getContentResolver(),
5303 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005304 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005305 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005306 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005308 }
5309
5310 public boolean isSafeMode() {
5311 return mSafeMode;
5312 }
5313
5314 public boolean hasSystemUidErrors() {
5315 return mHasSystemUidErrors;
5316 }
5317
5318 static String arrayToString(int[] array) {
5319 StringBuffer buf = new StringBuffer(128);
5320 buf.append('[');
5321 if (array != null) {
5322 for (int i=0; i<array.length; i++) {
5323 if (i > 0) buf.append(", ");
5324 buf.append(array[i]);
5325 }
5326 }
5327 buf.append(']');
5328 return buf.toString();
5329 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 @Override
5332 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5333 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5334 != PackageManager.PERMISSION_GRANTED) {
5335 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5336 + Binder.getCallingPid()
5337 + ", uid=" + Binder.getCallingUid()
5338 + " without permission "
5339 + android.Manifest.permission.DUMP);
5340 return;
5341 }
5342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005343 synchronized (mPackages) {
5344 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005345 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 pw.println(" ");
5347 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005348 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005349 pw.println(" ");
5350 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005351 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 pw.println(" ");
5353 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005354 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005356 pw.println("Permissions:");
5357 {
5358 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005359 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5360 pw.print(Integer.toHexString(System.identityHashCode(p)));
5361 pw.println("):");
5362 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5363 pw.print(" uid="); pw.print(p.uid);
5364 pw.print(" gids="); pw.print(arrayToString(p.gids));
5365 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 }
5367 }
5368 pw.println(" ");
5369 pw.println("Packages:");
5370 {
5371 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005372 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5373 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5374 pw.println("):");
5375 pw.print(" userId="); pw.print(ps.userId);
5376 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5377 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5378 pw.print(" pkg="); pw.println(ps.pkg);
5379 pw.print(" codePath="); pw.println(ps.codePathString);
5380 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005381 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005382 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005383 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005384 pw.print(" supportsScreens=[");
5385 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005386 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005387 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005388 if (!first) pw.print(", ");
5389 first = false;
5390 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005391 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005392 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005393 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005394 if (!first) pw.print(", ");
5395 first = false;
5396 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005397 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005398 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005399 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005400 if (!first) pw.print(", ");
5401 first = false;
5402 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005403 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005404 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005405 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005406 if (!first) pw.print(", ");
5407 first = false;
5408 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005409 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005410 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005411 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5412 if (!first) pw.print(", ");
5413 first = false;
5414 pw.print("anyDensity");
5415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005416 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005417 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005418 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5419 pw.print(" signatures="); pw.println(ps.signatures);
5420 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5421 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5422 pw.print(" installStatus="); pw.print(ps.installStatus);
5423 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 if (ps.disabledComponents.size() > 0) {
5425 pw.println(" disabledComponents:");
5426 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005427 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 }
5429 }
5430 if (ps.enabledComponents.size() > 0) {
5431 pw.println(" enabledComponents:");
5432 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005433 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 }
5435 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005436 if (ps.grantedPermissions.size() > 0) {
5437 pw.println(" grantedPermissions:");
5438 for (String s : ps.grantedPermissions) {
5439 pw.print(" "); pw.println(s);
5440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005441 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005442 if (ps.loadedPermissions.size() > 0) {
5443 pw.println(" loadedPermissions:");
5444 for (String s : ps.loadedPermissions) {
5445 pw.print(" "); pw.println(s);
5446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005447 }
5448 }
5449 }
5450 pw.println(" ");
5451 pw.println("Shared Users:");
5452 {
5453 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005454 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5455 pw.print(Integer.toHexString(System.identityHashCode(su)));
5456 pw.println("):");
5457 pw.print(" userId="); pw.print(su.userId);
5458 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005459 pw.println(" grantedPermissions:");
5460 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005461 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005462 }
5463 pw.println(" loadedPermissions:");
5464 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005465 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 }
5467 }
5468 }
5469 pw.println(" ");
5470 pw.println("Settings parse messages:");
5471 pw.println(mSettings.mReadMessages.toString());
5472 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005473
5474 synchronized (mProviders) {
5475 pw.println(" ");
5476 pw.println("Registered ContentProviders:");
5477 for (PackageParser.Provider p : mProviders.values()) {
5478 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5479 pw.println(p.toString());
5480 }
5481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005482 }
5483
5484 static final class BasePermission {
5485 final static int TYPE_NORMAL = 0;
5486 final static int TYPE_BUILTIN = 1;
5487 final static int TYPE_DYNAMIC = 2;
5488
5489 final String name;
5490 final String sourcePackage;
5491 final int type;
5492 PackageParser.Permission perm;
5493 PermissionInfo pendingInfo;
5494 int uid;
5495 int[] gids;
5496
5497 BasePermission(String _name, String _sourcePackage, int _type) {
5498 name = _name;
5499 sourcePackage = _sourcePackage;
5500 type = _type;
5501 }
5502 }
5503
5504 static class PackageSignatures {
5505 private Signature[] mSignatures;
5506
5507 PackageSignatures(Signature[] sigs) {
5508 assignSignatures(sigs);
5509 }
5510
5511 PackageSignatures() {
5512 }
5513
5514 void writeXml(XmlSerializer serializer, String tagName,
5515 ArrayList<Signature> pastSignatures) throws IOException {
5516 if (mSignatures == null) {
5517 return;
5518 }
5519 serializer.startTag(null, tagName);
5520 serializer.attribute(null, "count",
5521 Integer.toString(mSignatures.length));
5522 for (int i=0; i<mSignatures.length; i++) {
5523 serializer.startTag(null, "cert");
5524 final Signature sig = mSignatures[i];
5525 final int sigHash = sig.hashCode();
5526 final int numPast = pastSignatures.size();
5527 int j;
5528 for (j=0; j<numPast; j++) {
5529 Signature pastSig = pastSignatures.get(j);
5530 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5531 serializer.attribute(null, "index", Integer.toString(j));
5532 break;
5533 }
5534 }
5535 if (j >= numPast) {
5536 pastSignatures.add(sig);
5537 serializer.attribute(null, "index", Integer.toString(numPast));
5538 serializer.attribute(null, "key", sig.toCharsString());
5539 }
5540 serializer.endTag(null, "cert");
5541 }
5542 serializer.endTag(null, tagName);
5543 }
5544
5545 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5546 throws IOException, XmlPullParserException {
5547 String countStr = parser.getAttributeValue(null, "count");
5548 if (countStr == null) {
5549 reportSettingsProblem(Log.WARN,
5550 "Error in package manager settings: <signatures> has"
5551 + " no count at " + parser.getPositionDescription());
5552 XmlUtils.skipCurrentTag(parser);
5553 }
5554 final int count = Integer.parseInt(countStr);
5555 mSignatures = new Signature[count];
5556 int pos = 0;
5557
5558 int outerDepth = parser.getDepth();
5559 int type;
5560 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5561 && (type != XmlPullParser.END_TAG
5562 || parser.getDepth() > outerDepth)) {
5563 if (type == XmlPullParser.END_TAG
5564 || type == XmlPullParser.TEXT) {
5565 continue;
5566 }
5567
5568 String tagName = parser.getName();
5569 if (tagName.equals("cert")) {
5570 if (pos < count) {
5571 String index = parser.getAttributeValue(null, "index");
5572 if (index != null) {
5573 try {
5574 int idx = Integer.parseInt(index);
5575 String key = parser.getAttributeValue(null, "key");
5576 if (key == null) {
5577 if (idx >= 0 && idx < pastSignatures.size()) {
5578 Signature sig = pastSignatures.get(idx);
5579 if (sig != null) {
5580 mSignatures[pos] = pastSignatures.get(idx);
5581 pos++;
5582 } else {
5583 reportSettingsProblem(Log.WARN,
5584 "Error in package manager settings: <cert> "
5585 + "index " + index + " is not defined at "
5586 + parser.getPositionDescription());
5587 }
5588 } else {
5589 reportSettingsProblem(Log.WARN,
5590 "Error in package manager settings: <cert> "
5591 + "index " + index + " is out of bounds at "
5592 + parser.getPositionDescription());
5593 }
5594 } else {
5595 while (pastSignatures.size() <= idx) {
5596 pastSignatures.add(null);
5597 }
5598 Signature sig = new Signature(key);
5599 pastSignatures.set(idx, sig);
5600 mSignatures[pos] = sig;
5601 pos++;
5602 }
5603 } catch (NumberFormatException e) {
5604 reportSettingsProblem(Log.WARN,
5605 "Error in package manager settings: <cert> "
5606 + "index " + index + " is not a number at "
5607 + parser.getPositionDescription());
5608 }
5609 } else {
5610 reportSettingsProblem(Log.WARN,
5611 "Error in package manager settings: <cert> has"
5612 + " no index at " + parser.getPositionDescription());
5613 }
5614 } else {
5615 reportSettingsProblem(Log.WARN,
5616 "Error in package manager settings: too "
5617 + "many <cert> tags, expected " + count
5618 + " at " + parser.getPositionDescription());
5619 }
5620 } else {
5621 reportSettingsProblem(Log.WARN,
5622 "Unknown element under <cert>: "
5623 + parser.getName());
5624 }
5625 XmlUtils.skipCurrentTag(parser);
5626 }
5627
5628 if (pos < count) {
5629 // Should never happen -- there is an error in the written
5630 // settings -- but if it does we don't want to generate
5631 // a bad array.
5632 Signature[] newSigs = new Signature[pos];
5633 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5634 mSignatures = newSigs;
5635 }
5636 }
5637
5638 /**
5639 * If any of the given 'sigs' is contained in the existing signatures,
5640 * then completely replace the current signatures with the ones in
5641 * 'sigs'. This is used for updating an existing package to a newly
5642 * installed version.
5643 */
5644 boolean updateSignatures(Signature[] sigs, boolean update) {
5645 if (mSignatures == null) {
5646 if (update) {
5647 assignSignatures(sigs);
5648 }
5649 return true;
5650 }
5651 if (sigs == null) {
5652 return false;
5653 }
5654
5655 for (int i=0; i<sigs.length; i++) {
5656 Signature sig = sigs[i];
5657 for (int j=0; j<mSignatures.length; j++) {
5658 if (mSignatures[j].equals(sig)) {
5659 if (update) {
5660 assignSignatures(sigs);
5661 }
5662 return true;
5663 }
5664 }
5665 }
5666 return false;
5667 }
5668
5669 /**
5670 * If any of the given 'sigs' is contained in the existing signatures,
5671 * then add in any new signatures found in 'sigs'. This is used for
5672 * including a new package into an existing shared user id.
5673 */
5674 boolean mergeSignatures(Signature[] sigs, boolean update) {
5675 if (mSignatures == null) {
5676 if (update) {
5677 assignSignatures(sigs);
5678 }
5679 return true;
5680 }
5681 if (sigs == null) {
5682 return false;
5683 }
5684
5685 Signature[] added = null;
5686 int addedCount = 0;
5687 boolean haveMatch = false;
5688 for (int i=0; i<sigs.length; i++) {
5689 Signature sig = sigs[i];
5690 boolean found = false;
5691 for (int j=0; j<mSignatures.length; j++) {
5692 if (mSignatures[j].equals(sig)) {
5693 found = true;
5694 haveMatch = true;
5695 break;
5696 }
5697 }
5698
5699 if (!found) {
5700 if (added == null) {
5701 added = new Signature[sigs.length];
5702 }
5703 added[i] = sig;
5704 addedCount++;
5705 }
5706 }
5707
5708 if (!haveMatch) {
5709 // Nothing matched -- reject the new signatures.
5710 return false;
5711 }
5712 if (added == null) {
5713 // Completely matched -- nothing else to do.
5714 return true;
5715 }
5716
5717 // Add additional signatures in.
5718 if (update) {
5719 Signature[] total = new Signature[addedCount+mSignatures.length];
5720 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5721 int j = mSignatures.length;
5722 for (int i=0; i<added.length; i++) {
5723 if (added[i] != null) {
5724 total[j] = added[i];
5725 j++;
5726 }
5727 }
5728 mSignatures = total;
5729 }
5730 return true;
5731 }
5732
5733 private void assignSignatures(Signature[] sigs) {
5734 if (sigs == null) {
5735 mSignatures = null;
5736 return;
5737 }
5738 mSignatures = new Signature[sigs.length];
5739 for (int i=0; i<sigs.length; i++) {
5740 mSignatures[i] = sigs[i];
5741 }
5742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 @Override
5745 public String toString() {
5746 StringBuffer buf = new StringBuffer(128);
5747 buf.append("PackageSignatures{");
5748 buf.append(Integer.toHexString(System.identityHashCode(this)));
5749 buf.append(" [");
5750 if (mSignatures != null) {
5751 for (int i=0; i<mSignatures.length; i++) {
5752 if (i > 0) buf.append(", ");
5753 buf.append(Integer.toHexString(
5754 System.identityHashCode(mSignatures[i])));
5755 }
5756 }
5757 buf.append("]}");
5758 return buf.toString();
5759 }
5760 }
5761
5762 static class PreferredActivity extends IntentFilter {
5763 final int mMatch;
5764 final String[] mSetPackages;
5765 final String[] mSetClasses;
5766 final String[] mSetComponents;
5767 final ComponentName mActivity;
5768 final String mShortActivity;
5769 String mParseError;
5770
5771 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5772 ComponentName activity) {
5773 super(filter);
5774 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5775 mActivity = activity;
5776 mShortActivity = activity.flattenToShortString();
5777 mParseError = null;
5778 if (set != null) {
5779 final int N = set.length;
5780 String[] myPackages = new String[N];
5781 String[] myClasses = new String[N];
5782 String[] myComponents = new String[N];
5783 for (int i=0; i<N; i++) {
5784 ComponentName cn = set[i];
5785 if (cn == null) {
5786 mSetPackages = null;
5787 mSetClasses = null;
5788 mSetComponents = null;
5789 return;
5790 }
5791 myPackages[i] = cn.getPackageName().intern();
5792 myClasses[i] = cn.getClassName().intern();
5793 myComponents[i] = cn.flattenToShortString().intern();
5794 }
5795 mSetPackages = myPackages;
5796 mSetClasses = myClasses;
5797 mSetComponents = myComponents;
5798 } else {
5799 mSetPackages = null;
5800 mSetClasses = null;
5801 mSetComponents = null;
5802 }
5803 }
5804
5805 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5806 IOException {
5807 mShortActivity = parser.getAttributeValue(null, "name");
5808 mActivity = ComponentName.unflattenFromString(mShortActivity);
5809 if (mActivity == null) {
5810 mParseError = "Bad activity name " + mShortActivity;
5811 }
5812 String matchStr = parser.getAttributeValue(null, "match");
5813 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5814 String setCountStr = parser.getAttributeValue(null, "set");
5815 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5816
5817 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5818 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5819 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5820
5821 int setPos = 0;
5822
5823 int outerDepth = parser.getDepth();
5824 int type;
5825 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5826 && (type != XmlPullParser.END_TAG
5827 || parser.getDepth() > outerDepth)) {
5828 if (type == XmlPullParser.END_TAG
5829 || type == XmlPullParser.TEXT) {
5830 continue;
5831 }
5832
5833 String tagName = parser.getName();
5834 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5835 // + parser.getDepth() + " tag=" + tagName);
5836 if (tagName.equals("set")) {
5837 String name = parser.getAttributeValue(null, "name");
5838 if (name == null) {
5839 if (mParseError == null) {
5840 mParseError = "No name in set tag in preferred activity "
5841 + mShortActivity;
5842 }
5843 } else if (setPos >= setCount) {
5844 if (mParseError == null) {
5845 mParseError = "Too many set tags in preferred activity "
5846 + mShortActivity;
5847 }
5848 } else {
5849 ComponentName cn = ComponentName.unflattenFromString(name);
5850 if (cn == null) {
5851 if (mParseError == null) {
5852 mParseError = "Bad set name " + name + " in preferred activity "
5853 + mShortActivity;
5854 }
5855 } else {
5856 myPackages[setPos] = cn.getPackageName();
5857 myClasses[setPos] = cn.getClassName();
5858 myComponents[setPos] = name;
5859 setPos++;
5860 }
5861 }
5862 XmlUtils.skipCurrentTag(parser);
5863 } else if (tagName.equals("filter")) {
5864 //Log.i(TAG, "Starting to parse filter...");
5865 readFromXml(parser);
5866 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5867 // + parser.getDepth() + " tag=" + parser.getName());
5868 } else {
5869 reportSettingsProblem(Log.WARN,
5870 "Unknown element under <preferred-activities>: "
5871 + parser.getName());
5872 XmlUtils.skipCurrentTag(parser);
5873 }
5874 }
5875
5876 if (setPos != setCount) {
5877 if (mParseError == null) {
5878 mParseError = "Not enough set tags (expected " + setCount
5879 + " but found " + setPos + ") in " + mShortActivity;
5880 }
5881 }
5882
5883 mSetPackages = myPackages;
5884 mSetClasses = myClasses;
5885 mSetComponents = myComponents;
5886 }
5887
5888 public void writeToXml(XmlSerializer serializer) throws IOException {
5889 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5890 serializer.attribute(null, "name", mShortActivity);
5891 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5892 serializer.attribute(null, "set", Integer.toString(NS));
5893 for (int s=0; s<NS; s++) {
5894 serializer.startTag(null, "set");
5895 serializer.attribute(null, "name", mSetComponents[s]);
5896 serializer.endTag(null, "set");
5897 }
5898 serializer.startTag(null, "filter");
5899 super.writeToXml(serializer);
5900 serializer.endTag(null, "filter");
5901 }
5902
5903 boolean sameSet(List<ResolveInfo> query, int priority) {
5904 if (mSetPackages == null) return false;
5905 final int NQ = query.size();
5906 final int NS = mSetPackages.length;
5907 int numMatch = 0;
5908 for (int i=0; i<NQ; i++) {
5909 ResolveInfo ri = query.get(i);
5910 if (ri.priority != priority) continue;
5911 ActivityInfo ai = ri.activityInfo;
5912 boolean good = false;
5913 for (int j=0; j<NS; j++) {
5914 if (mSetPackages[j].equals(ai.packageName)
5915 && mSetClasses[j].equals(ai.name)) {
5916 numMatch++;
5917 good = true;
5918 break;
5919 }
5920 }
5921 if (!good) return false;
5922 }
5923 return numMatch == NS;
5924 }
5925 }
5926
5927 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005928 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 HashSet<String> grantedPermissions = new HashSet<String>();
5931 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005933 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08005936 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
5937 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
5938 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 }
5940 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005942 /**
5943 * Settings base class for pending and resolved classes.
5944 */
5945 static class PackageSettingBase extends GrantedPermissions {
5946 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005947 File codePath;
5948 String codePathString;
5949 File resourcePath;
5950 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 private long timeStamp;
5952 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005953 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005954
5955 PackageSignatures signatures = new PackageSignatures();
5956
5957 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959 /* Explicitly disabled components */
5960 HashSet<String> disabledComponents = new HashSet<String>(0);
5961 /* Explicitly enabled components */
5962 HashSet<String> enabledComponents = new HashSet<String>(0);
5963 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5964 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005965
Jacek Surazski65e13172009-04-28 15:26:38 +02005966 /* package name of the app that installed this package */
5967 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005968
5969 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005970 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 super(pkgFlags);
5972 this.name = name;
5973 this.codePath = codePath;
5974 this.codePathString = codePath.toString();
5975 this.resourcePath = resourcePath;
5976 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005977 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 }
5979
Jacek Surazski65e13172009-04-28 15:26:38 +02005980 public void setInstallerPackageName(String packageName) {
5981 installerPackageName = packageName;
5982 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005983
Jacek Surazski65e13172009-04-28 15:26:38 +02005984 String getInstallerPackageName() {
5985 return installerPackageName;
5986 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 public void setInstallStatus(int newStatus) {
5989 installStatus = newStatus;
5990 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005992 public int getInstallStatus() {
5993 return installStatus;
5994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 public void setTimeStamp(long newStamp) {
5997 if (newStamp != timeStamp) {
5998 timeStamp = newStamp;
5999 timeStampString = Long.toString(newStamp);
6000 }
6001 }
6002
6003 public void setTimeStamp(long newStamp, String newStampStr) {
6004 timeStamp = newStamp;
6005 timeStampString = newStampStr;
6006 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006008 public long getTimeStamp() {
6009 return timeStamp;
6010 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006012 public String getTimeStampStr() {
6013 return timeStampString;
6014 }
6015
6016 public void copyFrom(PackageSettingBase base) {
6017 grantedPermissions = base.grantedPermissions;
6018 gids = base.gids;
6019 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006021 timeStamp = base.timeStamp;
6022 timeStampString = base.timeStampString;
6023 signatures = base.signatures;
6024 permissionsFixed = base.permissionsFixed;
6025 disabledComponents = base.disabledComponents;
6026 enabledComponents = base.enabledComponents;
6027 enabled = base.enabled;
6028 installStatus = base.installStatus;
6029 }
6030
6031 void enableComponentLP(String componentClassName) {
6032 disabledComponents.remove(componentClassName);
6033 enabledComponents.add(componentClassName);
6034 }
6035
6036 void disableComponentLP(String componentClassName) {
6037 enabledComponents.remove(componentClassName);
6038 disabledComponents.add(componentClassName);
6039 }
6040
6041 void restoreComponentLP(String componentClassName) {
6042 enabledComponents.remove(componentClassName);
6043 disabledComponents.remove(componentClassName);
6044 }
6045
6046 int currentEnabledStateLP(String componentName) {
6047 if (enabledComponents.contains(componentName)) {
6048 return COMPONENT_ENABLED_STATE_ENABLED;
6049 } else if (disabledComponents.contains(componentName)) {
6050 return COMPONENT_ENABLED_STATE_DISABLED;
6051 } else {
6052 return COMPONENT_ENABLED_STATE_DEFAULT;
6053 }
6054 }
6055 }
6056
6057 /**
6058 * Settings data for a particular package we know about.
6059 */
6060 static final class PackageSetting extends PackageSettingBase {
6061 int userId;
6062 PackageParser.Package pkg;
6063 SharedUserSetting sharedUser;
6064
6065 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006066 int pVersionCode, int pkgFlags) {
6067 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006068 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070 @Override
6071 public String toString() {
6072 return "PackageSetting{"
6073 + Integer.toHexString(System.identityHashCode(this))
6074 + " " + name + "/" + userId + "}";
6075 }
6076 }
6077
6078 /**
6079 * Settings data for a particular shared user ID we know about.
6080 */
6081 static final class SharedUserSetting extends GrantedPermissions {
6082 final String name;
6083 int userId;
6084 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6085 final PackageSignatures signatures = new PackageSignatures();
6086
6087 SharedUserSetting(String _name, int _pkgFlags) {
6088 super(_pkgFlags);
6089 name = _name;
6090 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 @Override
6093 public String toString() {
6094 return "SharedUserSetting{"
6095 + Integer.toHexString(System.identityHashCode(this))
6096 + " " + name + "/" + userId + "}";
6097 }
6098 }
6099
6100 /**
6101 * Holds information about dynamic settings.
6102 */
6103 private static final class Settings {
6104 private final File mSettingsFilename;
6105 private final File mBackupSettingsFilename;
6106 private final HashMap<String, PackageSetting> mPackages =
6107 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 // List of replaced system applications
6109 final HashMap<String, PackageSetting> mDisabledSysPackages =
6110 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 // The user's preferred activities associated with particular intent
6113 // filters.
6114 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6115 new IntentResolver<PreferredActivity, PreferredActivity>() {
6116 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006117 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006118 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006119 out.print(prefix); out.print(
6120 Integer.toHexString(System.identityHashCode(filter)));
6121 out.print(' ');
6122 out.print(filter.mActivity.flattenToShortString());
6123 out.print(" match=0x");
6124 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006126 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006128 out.print(prefix); out.print(" ");
6129 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006130 }
6131 }
6132 }
6133 };
6134 private final HashMap<String, SharedUserSetting> mSharedUsers =
6135 new HashMap<String, SharedUserSetting>();
6136 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6137 private final SparseArray<Object> mOtherUserIds =
6138 new SparseArray<Object>();
6139
6140 // For reading/writing settings file.
6141 private final ArrayList<Signature> mPastSignatures =
6142 new ArrayList<Signature>();
6143
6144 // Mapping from permission names to info about them.
6145 final HashMap<String, BasePermission> mPermissions =
6146 new HashMap<String, BasePermission>();
6147
6148 // Mapping from permission tree names to info about them.
6149 final HashMap<String, BasePermission> mPermissionTrees =
6150 new HashMap<String, BasePermission>();
6151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006152 private final StringBuilder mReadMessages = new StringBuilder();
6153
6154 private static final class PendingPackage extends PackageSettingBase {
6155 final int sharedId;
6156
6157 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006158 int sharedId, int pVersionCode, int pkgFlags) {
6159 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 this.sharedId = sharedId;
6161 }
6162 }
6163 private final ArrayList<PendingPackage> mPendingPackages
6164 = new ArrayList<PendingPackage>();
6165
6166 Settings() {
6167 File dataDir = Environment.getDataDirectory();
6168 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006169 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6170 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006172 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 FileUtils.setPermissions(systemDir.toString(),
6174 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6175 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6176 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006177 FileUtils.setPermissions(systemSecureDir.toString(),
6178 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6179 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6180 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006181 mSettingsFilename = new File(systemDir, "packages.xml");
6182 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6183 }
6184
6185 PackageSetting getPackageLP(PackageParser.Package pkg,
6186 SharedUserSetting sharedUser, File codePath, File resourcePath,
6187 int pkgFlags, boolean create, boolean add) {
6188 final String name = pkg.packageName;
6189 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006190 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 return p;
6192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006193
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006194 PackageSetting peekPackageLP(String name) {
6195 return mPackages.get(name);
6196 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006197 PackageSetting p = mPackages.get(name);
6198 if (p != null && p.codePath.getPath().equals(codePath)) {
6199 return p;
6200 }
6201 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006202 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006203 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006205 void setInstallStatus(String pkgName, int status) {
6206 PackageSetting p = mPackages.get(pkgName);
6207 if(p != null) {
6208 if(p.getInstallStatus() != status) {
6209 p.setInstallStatus(status);
6210 }
6211 }
6212 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006213
Jacek Surazski65e13172009-04-28 15:26:38 +02006214 void setInstallerPackageName(String pkgName,
6215 String installerPkgName) {
6216 PackageSetting p = mPackages.get(pkgName);
6217 if(p != null) {
6218 p.setInstallerPackageName(installerPkgName);
6219 }
6220 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006221
Jacek Surazski65e13172009-04-28 15:26:38 +02006222 String getInstallerPackageName(String pkgName) {
6223 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006224 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006225 }
6226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 int getInstallStatus(String pkgName) {
6228 PackageSetting p = mPackages.get(pkgName);
6229 if(p != null) {
6230 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 return -1;
6233 }
6234
6235 SharedUserSetting getSharedUserLP(String name,
6236 int pkgFlags, boolean create) {
6237 SharedUserSetting s = mSharedUsers.get(name);
6238 if (s == null) {
6239 if (!create) {
6240 return null;
6241 }
6242 s = new SharedUserSetting(name, pkgFlags);
6243 if (MULTIPLE_APPLICATION_UIDS) {
6244 s.userId = newUserIdLP(s);
6245 } else {
6246 s.userId = FIRST_APPLICATION_UID;
6247 }
6248 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6249 // < 0 means we couldn't assign a userid; fall out and return
6250 // s, which is currently null
6251 if (s.userId >= 0) {
6252 mSharedUsers.put(name, s);
6253 }
6254 }
6255
6256 return s;
6257 }
6258
6259 int disableSystemPackageLP(String name) {
6260 PackageSetting p = mPackages.get(name);
6261 if(p == null) {
6262 Log.w(TAG, "Package:"+name+" is not an installed package");
6263 return -1;
6264 }
6265 PackageSetting dp = mDisabledSysPackages.get(name);
6266 // always make sure the system package code and resource paths dont change
6267 if(dp == null) {
6268 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6269 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6270 }
6271 mDisabledSysPackages.put(name, p);
6272 }
6273 return removePackageLP(name);
6274 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006276 PackageSetting enableSystemPackageLP(String name) {
6277 PackageSetting p = mDisabledSysPackages.get(name);
6278 if(p == null) {
6279 Log.w(TAG, "Package:"+name+" is not disabled");
6280 return null;
6281 }
6282 // Reset flag in ApplicationInfo object
6283 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6284 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6285 }
6286 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006287 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 mDisabledSysPackages.remove(name);
6289 return ret;
6290 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006293 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006294 PackageSetting p = mPackages.get(name);
6295 if (p != null) {
6296 if (p.userId == uid) {
6297 return p;
6298 }
6299 reportSettingsProblem(Log.ERROR,
6300 "Adding duplicate package, keeping first: " + name);
6301 return null;
6302 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006303 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 p.userId = uid;
6305 if (addUserIdLP(uid, p, name)) {
6306 mPackages.put(name, p);
6307 return p;
6308 }
6309 return null;
6310 }
6311
6312 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6313 SharedUserSetting s = mSharedUsers.get(name);
6314 if (s != null) {
6315 if (s.userId == uid) {
6316 return s;
6317 }
6318 reportSettingsProblem(Log.ERROR,
6319 "Adding duplicate shared user, keeping first: " + name);
6320 return null;
6321 }
6322 s = new SharedUserSetting(name, pkgFlags);
6323 s.userId = uid;
6324 if (addUserIdLP(uid, s, name)) {
6325 mSharedUsers.put(name, s);
6326 return s;
6327 }
6328 return null;
6329 }
6330
6331 private PackageSetting getPackageLP(String name,
6332 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006333 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 PackageSetting p = mPackages.get(name);
6335 if (p != null) {
6336 if (!p.codePath.equals(codePath)) {
6337 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006338 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006339 // This is an updated system app with versions in both system
6340 // and data partition. Just let the most recent version
6341 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006342 Log.w(TAG, "Trying to update system app code path from " +
6343 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006344 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006345 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006346 reportSettingsProblem(Log.WARN,
6347 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006348 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006350 }
6351 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006352 reportSettingsProblem(Log.WARN,
6353 "Package " + name + " shared user changed from "
6354 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6355 + " to "
6356 + (sharedUser != null ? sharedUser.name : "<nothing>")
6357 + "; replacing with new");
6358 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006359 } else {
6360 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6361 // If what we are scanning is a system package, then
6362 // make it so, regardless of whether it was previously
6363 // installed only in the data partition.
6364 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 }
6367 }
6368 if (p == null) {
6369 // Create a new PackageSettings entry. this can end up here because
6370 // of code path mismatch or user id mismatch of an updated system partition
6371 if (!create) {
6372 return null;
6373 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006374 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006376 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 if (sharedUser != null) {
6378 p.userId = sharedUser.userId;
6379 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006380 // Clone the setting here for disabled system packages
6381 PackageSetting dis = mDisabledSysPackages.get(name);
6382 if (dis != null) {
6383 // For disabled packages a new setting is created
6384 // from the existing user id. This still has to be
6385 // added to list of user id's
6386 // Copy signatures from previous setting
6387 if (dis.signatures.mSignatures != null) {
6388 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6389 }
6390 p.userId = dis.userId;
6391 // Clone permissions
6392 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6393 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6394 // Clone component info
6395 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6396 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6397 // Add new setting to list of user ids
6398 addUserIdLP(p.userId, p, name);
6399 } else {
6400 // Assign new user id
6401 p.userId = newUserIdLP(p);
6402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 } else {
6404 p.userId = FIRST_APPLICATION_UID;
6405 }
6406 if (p.userId < 0) {
6407 reportSettingsProblem(Log.WARN,
6408 "Package " + name + " could not be assigned a valid uid");
6409 return null;
6410 }
6411 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006412 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006414 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006415 }
6416 }
6417 return p;
6418 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006419
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006420 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006421 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006422 String codePath = pkg.applicationInfo.sourceDir;
6423 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006424 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006425 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006426 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006427 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006428 p.codePath = new File(codePath);
6429 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006430 }
6431 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006432 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006433 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006434 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006435 p.resourcePath = new File(resourcePath);
6436 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006437 }
6438 // Update version code if needed
6439 if (pkg.mVersionCode != p.versionCode) {
6440 p.versionCode = pkg.mVersionCode;
6441 }
6442 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6443 }
6444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 // Utility method that adds a PackageSetting to mPackages and
6446 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006447 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006448 SharedUserSetting sharedUser) {
6449 mPackages.put(name, p);
6450 if (sharedUser != null) {
6451 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6452 reportSettingsProblem(Log.ERROR,
6453 "Package " + p.name + " was user "
6454 + p.sharedUser + " but is now " + sharedUser
6455 + "; I am not changing its files so it will probably fail!");
6456 p.sharedUser.packages.remove(p);
6457 } else if (p.userId != sharedUser.userId) {
6458 reportSettingsProblem(Log.ERROR,
6459 "Package " + p.name + " was user id " + p.userId
6460 + " but is now user " + sharedUser
6461 + " with id " + sharedUser.userId
6462 + "; I am not changing its files so it will probably fail!");
6463 }
6464
6465 sharedUser.packages.add(p);
6466 p.sharedUser = sharedUser;
6467 p.userId = sharedUser.userId;
6468 }
6469 }
6470
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006471 /*
6472 * Update the shared user setting when a package using
6473 * specifying the shared user id is removed. The gids
6474 * associated with each permission of the deleted package
6475 * are removed from the shared user's gid list only if its
6476 * not in use by other permissions of packages in the
6477 * shared user setting.
6478 */
6479 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006480 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6481 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6482 return;
6483 }
6484 // No sharedUserId
6485 if (deletedPs.sharedUser == null) {
6486 return;
6487 }
6488 SharedUserSetting sus = deletedPs.sharedUser;
6489 // Update permissions
6490 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6491 boolean used = false;
6492 if (!sus.grantedPermissions.contains (eachPerm)) {
6493 continue;
6494 }
6495 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006496 if (pkg.pkg != null &&
6497 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6498 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006499 used = true;
6500 break;
6501 }
6502 }
6503 if (!used) {
6504 // can safely delete this permission from list
6505 sus.grantedPermissions.remove(eachPerm);
6506 sus.loadedPermissions.remove(eachPerm);
6507 }
6508 }
6509 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006510 int newGids[] = globalGids;
6511 for (String eachPerm : sus.grantedPermissions) {
6512 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006513 if (bp != null) {
6514 newGids = appendInts(newGids, bp.gids);
6515 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006516 }
6517 sus.gids = newGids;
6518 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006520 private int removePackageLP(String name) {
6521 PackageSetting p = mPackages.get(name);
6522 if (p != null) {
6523 mPackages.remove(name);
6524 if (p.sharedUser != null) {
6525 p.sharedUser.packages.remove(p);
6526 if (p.sharedUser.packages.size() == 0) {
6527 mSharedUsers.remove(p.sharedUser.name);
6528 removeUserIdLP(p.sharedUser.userId);
6529 return p.sharedUser.userId;
6530 }
6531 } else {
6532 removeUserIdLP(p.userId);
6533 return p.userId;
6534 }
6535 }
6536 return -1;
6537 }
6538
6539 private boolean addUserIdLP(int uid, Object obj, Object name) {
6540 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6541 return false;
6542 }
6543
6544 if (uid >= FIRST_APPLICATION_UID) {
6545 int N = mUserIds.size();
6546 final int index = uid - FIRST_APPLICATION_UID;
6547 while (index >= N) {
6548 mUserIds.add(null);
6549 N++;
6550 }
6551 if (mUserIds.get(index) != null) {
6552 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006553 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006554 + " name=" + name);
6555 return false;
6556 }
6557 mUserIds.set(index, obj);
6558 } else {
6559 if (mOtherUserIds.get(uid) != null) {
6560 reportSettingsProblem(Log.ERROR,
6561 "Adding duplicate shared id: " + uid
6562 + " name=" + name);
6563 return false;
6564 }
6565 mOtherUserIds.put(uid, obj);
6566 }
6567 return true;
6568 }
6569
6570 public Object getUserIdLP(int uid) {
6571 if (uid >= FIRST_APPLICATION_UID) {
6572 int N = mUserIds.size();
6573 final int index = uid - FIRST_APPLICATION_UID;
6574 return index < N ? mUserIds.get(index) : null;
6575 } else {
6576 return mOtherUserIds.get(uid);
6577 }
6578 }
6579
6580 private void removeUserIdLP(int uid) {
6581 if (uid >= FIRST_APPLICATION_UID) {
6582 int N = mUserIds.size();
6583 final int index = uid - FIRST_APPLICATION_UID;
6584 if (index < N) mUserIds.set(index, null);
6585 } else {
6586 mOtherUserIds.remove(uid);
6587 }
6588 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006590 void writeLP() {
6591 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6592
6593 // Keep the old settings around until we know the new ones have
6594 // been successfully written.
6595 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006596 // Presence of backup settings file indicates that we failed
6597 // to persist settings earlier. So preserve the older
6598 // backup for future reference since the current settings
6599 // might have been corrupted.
6600 if (!mBackupSettingsFilename.exists()) {
6601 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6602 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6603 return;
6604 }
6605 } else {
6606 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006607 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 }
6609
6610 mPastSignatures.clear();
6611
6612 try {
6613 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6614
6615 //XmlSerializer serializer = XmlUtils.serializerInstance();
6616 XmlSerializer serializer = new FastXmlSerializer();
6617 serializer.setOutput(str, "utf-8");
6618 serializer.startDocument(null, true);
6619 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6620
6621 serializer.startTag(null, "packages");
6622
6623 serializer.startTag(null, "permission-trees");
6624 for (BasePermission bp : mPermissionTrees.values()) {
6625 writePermission(serializer, bp);
6626 }
6627 serializer.endTag(null, "permission-trees");
6628
6629 serializer.startTag(null, "permissions");
6630 for (BasePermission bp : mPermissions.values()) {
6631 writePermission(serializer, bp);
6632 }
6633 serializer.endTag(null, "permissions");
6634
6635 for (PackageSetting pkg : mPackages.values()) {
6636 writePackage(serializer, pkg);
6637 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6640 writeDisabledSysPackage(serializer, pkg);
6641 }
6642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 serializer.startTag(null, "preferred-activities");
6644 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6645 serializer.startTag(null, "item");
6646 pa.writeToXml(serializer);
6647 serializer.endTag(null, "item");
6648 }
6649 serializer.endTag(null, "preferred-activities");
6650
6651 for (SharedUserSetting usr : mSharedUsers.values()) {
6652 serializer.startTag(null, "shared-user");
6653 serializer.attribute(null, "name", usr.name);
6654 serializer.attribute(null, "userId",
6655 Integer.toString(usr.userId));
6656 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6657 serializer.startTag(null, "perms");
6658 for (String name : usr.grantedPermissions) {
6659 serializer.startTag(null, "item");
6660 serializer.attribute(null, "name", name);
6661 serializer.endTag(null, "item");
6662 }
6663 serializer.endTag(null, "perms");
6664 serializer.endTag(null, "shared-user");
6665 }
6666
6667 serializer.endTag(null, "packages");
6668
6669 serializer.endDocument();
6670
6671 str.flush();
6672 str.close();
6673
6674 // New settings successfully written, old ones are no longer
6675 // needed.
6676 mBackupSettingsFilename.delete();
6677 FileUtils.setPermissions(mSettingsFilename.toString(),
6678 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6679 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6680 |FileUtils.S_IROTH,
6681 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006682 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683
6684 } catch(XmlPullParserException e) {
6685 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 -08006686 } catch(java.io.IOException e) {
6687 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 -08006688 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006689 // Clean up partially written file
6690 if (mSettingsFilename.exists()) {
6691 if (!mSettingsFilename.delete()) {
6692 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6693 }
6694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006695 //Debug.stopMethodTracing();
6696 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006697
6698 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 throws java.io.IOException {
6700 serializer.startTag(null, "updated-package");
6701 serializer.attribute(null, "name", pkg.name);
6702 serializer.attribute(null, "codePath", pkg.codePathString);
6703 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006704 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6706 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6707 }
6708 if (pkg.sharedUser == null) {
6709 serializer.attribute(null, "userId",
6710 Integer.toString(pkg.userId));
6711 } else {
6712 serializer.attribute(null, "sharedUserId",
6713 Integer.toString(pkg.userId));
6714 }
6715 serializer.startTag(null, "perms");
6716 if (pkg.sharedUser == null) {
6717 // If this is a shared user, the permissions will
6718 // be written there. We still need to write an
6719 // empty permissions list so permissionsFixed will
6720 // be set.
6721 for (final String name : pkg.grantedPermissions) {
6722 BasePermission bp = mPermissions.get(name);
6723 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6724 // We only need to write signature or system permissions but this wont
6725 // match the semantics of grantedPermissions. So write all permissions.
6726 serializer.startTag(null, "item");
6727 serializer.attribute(null, "name", name);
6728 serializer.endTag(null, "item");
6729 }
6730 }
6731 }
6732 serializer.endTag(null, "perms");
6733 serializer.endTag(null, "updated-package");
6734 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006735
6736 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 throws java.io.IOException {
6738 serializer.startTag(null, "package");
6739 serializer.attribute(null, "name", pkg.name);
6740 serializer.attribute(null, "codePath", pkg.codePathString);
6741 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6742 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6743 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08006744 serializer.attribute(null, "flags",
6745 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006747 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006748 if (pkg.sharedUser == null) {
6749 serializer.attribute(null, "userId",
6750 Integer.toString(pkg.userId));
6751 } else {
6752 serializer.attribute(null, "sharedUserId",
6753 Integer.toString(pkg.userId));
6754 }
6755 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6756 serializer.attribute(null, "enabled",
6757 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6758 ? "true" : "false");
6759 }
6760 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6761 serializer.attribute(null, "installStatus", "false");
6762 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006763 if (pkg.installerPackageName != null) {
6764 serializer.attribute(null, "installer", pkg.installerPackageName);
6765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006766 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6767 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6768 serializer.startTag(null, "perms");
6769 if (pkg.sharedUser == null) {
6770 // If this is a shared user, the permissions will
6771 // be written there. We still need to write an
6772 // empty permissions list so permissionsFixed will
6773 // be set.
6774 for (final String name : pkg.grantedPermissions) {
6775 serializer.startTag(null, "item");
6776 serializer.attribute(null, "name", name);
6777 serializer.endTag(null, "item");
6778 }
6779 }
6780 serializer.endTag(null, "perms");
6781 }
6782 if (pkg.disabledComponents.size() > 0) {
6783 serializer.startTag(null, "disabled-components");
6784 for (final String name : pkg.disabledComponents) {
6785 serializer.startTag(null, "item");
6786 serializer.attribute(null, "name", name);
6787 serializer.endTag(null, "item");
6788 }
6789 serializer.endTag(null, "disabled-components");
6790 }
6791 if (pkg.enabledComponents.size() > 0) {
6792 serializer.startTag(null, "enabled-components");
6793 for (final String name : pkg.enabledComponents) {
6794 serializer.startTag(null, "item");
6795 serializer.attribute(null, "name", name);
6796 serializer.endTag(null, "item");
6797 }
6798 serializer.endTag(null, "enabled-components");
6799 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 serializer.endTag(null, "package");
6802 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 void writePermission(XmlSerializer serializer, BasePermission bp)
6805 throws XmlPullParserException, java.io.IOException {
6806 if (bp.type != BasePermission.TYPE_BUILTIN
6807 && bp.sourcePackage != null) {
6808 serializer.startTag(null, "item");
6809 serializer.attribute(null, "name", bp.name);
6810 serializer.attribute(null, "package", bp.sourcePackage);
6811 if (DEBUG_SETTINGS) Log.v(TAG,
6812 "Writing perm: name=" + bp.name + " type=" + bp.type);
6813 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6814 PermissionInfo pi = bp.perm != null ? bp.perm.info
6815 : bp.pendingInfo;
6816 if (pi != null) {
6817 serializer.attribute(null, "type", "dynamic");
6818 if (pi.icon != 0) {
6819 serializer.attribute(null, "icon",
6820 Integer.toString(pi.icon));
6821 }
6822 if (pi.nonLocalizedLabel != null) {
6823 serializer.attribute(null, "label",
6824 pi.nonLocalizedLabel.toString());
6825 }
6826 if (pi.protectionLevel !=
6827 PermissionInfo.PROTECTION_NORMAL) {
6828 serializer.attribute(null, "protection",
6829 Integer.toString(pi.protectionLevel));
6830 }
6831 }
6832 }
6833 serializer.endTag(null, "item");
6834 }
6835 }
6836
6837 String getReadMessagesLP() {
6838 return mReadMessages.toString();
6839 }
6840
Oscar Montemayora8529f62009-11-18 10:14:20 -08006841 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6843 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006844 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006845 while(its.hasNext()) {
6846 String key = its.next();
6847 PackageSetting ps = mPackages.get(key);
6848 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006849 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 }
6851 }
6852 return ret;
6853 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 boolean readLP() {
6856 FileInputStream str = null;
6857 if (mBackupSettingsFilename.exists()) {
6858 try {
6859 str = new FileInputStream(mBackupSettingsFilename);
6860 mReadMessages.append("Reading from backup settings file\n");
6861 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006862 if (mSettingsFilename.exists()) {
6863 // If both the backup and settings file exist, we
6864 // ignore the settings since it might have been
6865 // corrupted.
6866 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6867 mSettingsFilename.delete();
6868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 } catch (java.io.IOException e) {
6870 // We'll try for the normal settings file.
6871 }
6872 }
6873
6874 mPastSignatures.clear();
6875
6876 try {
6877 if (str == null) {
6878 if (!mSettingsFilename.exists()) {
6879 mReadMessages.append("No settings file found\n");
6880 Log.i(TAG, "No current settings file!");
6881 return false;
6882 }
6883 str = new FileInputStream(mSettingsFilename);
6884 }
6885 XmlPullParser parser = Xml.newPullParser();
6886 parser.setInput(str, null);
6887
6888 int type;
6889 while ((type=parser.next()) != XmlPullParser.START_TAG
6890 && type != XmlPullParser.END_DOCUMENT) {
6891 ;
6892 }
6893
6894 if (type != XmlPullParser.START_TAG) {
6895 mReadMessages.append("No start tag found in settings file\n");
6896 Log.e(TAG, "No start tag found in package manager settings");
6897 return false;
6898 }
6899
6900 int outerDepth = parser.getDepth();
6901 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6902 && (type != XmlPullParser.END_TAG
6903 || parser.getDepth() > outerDepth)) {
6904 if (type == XmlPullParser.END_TAG
6905 || type == XmlPullParser.TEXT) {
6906 continue;
6907 }
6908
6909 String tagName = parser.getName();
6910 if (tagName.equals("package")) {
6911 readPackageLP(parser);
6912 } else if (tagName.equals("permissions")) {
6913 readPermissionsLP(mPermissions, parser);
6914 } else if (tagName.equals("permission-trees")) {
6915 readPermissionsLP(mPermissionTrees, parser);
6916 } else if (tagName.equals("shared-user")) {
6917 readSharedUserLP(parser);
6918 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006919 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 } else if (tagName.equals("preferred-activities")) {
6921 readPreferredActivitiesLP(parser);
6922 } else if(tagName.equals("updated-package")) {
6923 readDisabledSysPackageLP(parser);
6924 } else {
6925 Log.w(TAG, "Unknown element under <packages>: "
6926 + parser.getName());
6927 XmlUtils.skipCurrentTag(parser);
6928 }
6929 }
6930
6931 str.close();
6932
6933 } catch(XmlPullParserException e) {
6934 mReadMessages.append("Error reading: " + e.toString());
6935 Log.e(TAG, "Error reading package manager settings", e);
6936
6937 } catch(java.io.IOException e) {
6938 mReadMessages.append("Error reading: " + e.toString());
6939 Log.e(TAG, "Error reading package manager settings", e);
6940
6941 }
6942
6943 int N = mPendingPackages.size();
6944 for (int i=0; i<N; i++) {
6945 final PendingPackage pp = mPendingPackages.get(i);
6946 Object idObj = getUserIdLP(pp.sharedId);
6947 if (idObj != null && idObj instanceof SharedUserSetting) {
6948 PackageSetting p = getPackageLP(pp.name,
6949 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006950 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 if (p == null) {
6952 Log.w(TAG, "Unable to create application package for "
6953 + pp.name);
6954 continue;
6955 }
6956 p.copyFrom(pp);
6957 } else if (idObj != null) {
6958 String msg = "Bad package setting: package " + pp.name
6959 + " has shared uid " + pp.sharedId
6960 + " that is not a shared uid\n";
6961 mReadMessages.append(msg);
6962 Log.e(TAG, msg);
6963 } else {
6964 String msg = "Bad package setting: package " + pp.name
6965 + " has shared uid " + pp.sharedId
6966 + " that is not defined\n";
6967 mReadMessages.append(msg);
6968 Log.e(TAG, msg);
6969 }
6970 }
6971 mPendingPackages.clear();
6972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006973 mReadMessages.append("Read completed successfully: "
6974 + mPackages.size() + " packages, "
6975 + mSharedUsers.size() + " shared uids\n");
6976
6977 return true;
6978 }
6979
6980 private int readInt(XmlPullParser parser, String ns, String name,
6981 int defValue) {
6982 String v = parser.getAttributeValue(ns, name);
6983 try {
6984 if (v == null) {
6985 return defValue;
6986 }
6987 return Integer.parseInt(v);
6988 } catch (NumberFormatException e) {
6989 reportSettingsProblem(Log.WARN,
6990 "Error in package manager settings: attribute " +
6991 name + " has bad integer value " + v + " at "
6992 + parser.getPositionDescription());
6993 }
6994 return defValue;
6995 }
6996
6997 private void readPermissionsLP(HashMap<String, BasePermission> out,
6998 XmlPullParser parser)
6999 throws IOException, XmlPullParserException {
7000 int outerDepth = parser.getDepth();
7001 int type;
7002 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7003 && (type != XmlPullParser.END_TAG
7004 || parser.getDepth() > outerDepth)) {
7005 if (type == XmlPullParser.END_TAG
7006 || type == XmlPullParser.TEXT) {
7007 continue;
7008 }
7009
7010 String tagName = parser.getName();
7011 if (tagName.equals("item")) {
7012 String name = parser.getAttributeValue(null, "name");
7013 String sourcePackage = parser.getAttributeValue(null, "package");
7014 String ptype = parser.getAttributeValue(null, "type");
7015 if (name != null && sourcePackage != null) {
7016 boolean dynamic = "dynamic".equals(ptype);
7017 BasePermission bp = new BasePermission(name, sourcePackage,
7018 dynamic
7019 ? BasePermission.TYPE_DYNAMIC
7020 : BasePermission.TYPE_NORMAL);
7021 if (dynamic) {
7022 PermissionInfo pi = new PermissionInfo();
7023 pi.packageName = sourcePackage.intern();
7024 pi.name = name.intern();
7025 pi.icon = readInt(parser, null, "icon", 0);
7026 pi.nonLocalizedLabel = parser.getAttributeValue(
7027 null, "label");
7028 pi.protectionLevel = readInt(parser, null, "protection",
7029 PermissionInfo.PROTECTION_NORMAL);
7030 bp.pendingInfo = pi;
7031 }
7032 out.put(bp.name, bp);
7033 } else {
7034 reportSettingsProblem(Log.WARN,
7035 "Error in package manager settings: permissions has"
7036 + " no name at " + parser.getPositionDescription());
7037 }
7038 } else {
7039 reportSettingsProblem(Log.WARN,
7040 "Unknown element reading permissions: "
7041 + parser.getName() + " at "
7042 + parser.getPositionDescription());
7043 }
7044 XmlUtils.skipCurrentTag(parser);
7045 }
7046 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007048 private void readDisabledSysPackageLP(XmlPullParser parser)
7049 throws XmlPullParserException, IOException {
7050 String name = parser.getAttributeValue(null, "name");
7051 String codePathStr = parser.getAttributeValue(null, "codePath");
7052 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
7053 if(resourcePathStr == null) {
7054 resourcePathStr = codePathStr;
7055 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007056 String version = parser.getAttributeValue(null, "version");
7057 int versionCode = 0;
7058 if (version != null) {
7059 try {
7060 versionCode = Integer.parseInt(version);
7061 } catch (NumberFormatException e) {
7062 }
7063 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 int pkgFlags = 0;
7066 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007067 PackageSetting ps = new PackageSetting(name,
7068 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007069 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070 String timeStampStr = parser.getAttributeValue(null, "ts");
7071 if (timeStampStr != null) {
7072 try {
7073 long timeStamp = Long.parseLong(timeStampStr);
7074 ps.setTimeStamp(timeStamp, timeStampStr);
7075 } catch (NumberFormatException e) {
7076 }
7077 }
7078 String idStr = parser.getAttributeValue(null, "userId");
7079 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7080 if(ps.userId <= 0) {
7081 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7082 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7083 }
7084 int outerDepth = parser.getDepth();
7085 int type;
7086 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7087 && (type != XmlPullParser.END_TAG
7088 || parser.getDepth() > outerDepth)) {
7089 if (type == XmlPullParser.END_TAG
7090 || type == XmlPullParser.TEXT) {
7091 continue;
7092 }
7093
7094 String tagName = parser.getName();
7095 if (tagName.equals("perms")) {
7096 readGrantedPermissionsLP(parser,
7097 ps.grantedPermissions);
7098 } else {
7099 reportSettingsProblem(Log.WARN,
7100 "Unknown element under <updated-package>: "
7101 + parser.getName());
7102 XmlUtils.skipCurrentTag(parser);
7103 }
7104 }
7105 mDisabledSysPackages.put(name, ps);
7106 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 private void readPackageLP(XmlPullParser parser)
7109 throws XmlPullParserException, IOException {
7110 String name = null;
7111 String idStr = null;
7112 String sharedIdStr = null;
7113 String codePathStr = null;
7114 String resourcePathStr = null;
7115 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007116 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 int pkgFlags = 0;
7118 String timeStampStr;
7119 long timeStamp = 0;
7120 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007121 String version = null;
7122 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007123 try {
7124 name = parser.getAttributeValue(null, "name");
7125 idStr = parser.getAttributeValue(null, "userId");
7126 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7127 codePathStr = parser.getAttributeValue(null, "codePath");
7128 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007129 version = parser.getAttributeValue(null, "version");
7130 if (version != null) {
7131 try {
7132 versionCode = Integer.parseInt(version);
7133 } catch (NumberFormatException e) {
7134 }
7135 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007136 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007137
7138 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007140 try {
7141 pkgFlags = Integer.parseInt(systemStr);
7142 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007143 }
7144 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007145 // For backward compatibility
7146 systemStr = parser.getAttributeValue(null, "system");
7147 if (systemStr != null) {
7148 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
7149 } else {
7150 // Old settings that don't specify system... just treat
7151 // them as system, good enough.
7152 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007154 }
7155 timeStampStr = parser.getAttributeValue(null, "ts");
7156 if (timeStampStr != null) {
7157 try {
7158 timeStamp = Long.parseLong(timeStampStr);
7159 } catch (NumberFormatException e) {
7160 }
7161 }
7162 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7163 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7164 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7165 if (resourcePathStr == null) {
7166 resourcePathStr = codePathStr;
7167 }
7168 if (name == null) {
7169 reportSettingsProblem(Log.WARN,
7170 "Error in package manager settings: <package> has no name at "
7171 + parser.getPositionDescription());
7172 } else if (codePathStr == null) {
7173 reportSettingsProblem(Log.WARN,
7174 "Error in package manager settings: <package> has no codePath at "
7175 + parser.getPositionDescription());
7176 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007177 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007178 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007179 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7180 + ": userId=" + userId + " pkg=" + packageSetting);
7181 if (packageSetting == null) {
7182 reportSettingsProblem(Log.ERROR,
7183 "Failure adding uid " + userId
7184 + " while parsing settings at "
7185 + parser.getPositionDescription());
7186 } else {
7187 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7188 }
7189 } else if (sharedIdStr != null) {
7190 userId = sharedIdStr != null
7191 ? Integer.parseInt(sharedIdStr) : 0;
7192 if (userId > 0) {
7193 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007194 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7196 mPendingPackages.add((PendingPackage) packageSetting);
7197 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7198 + ": sharedUserId=" + userId + " pkg="
7199 + packageSetting);
7200 } else {
7201 reportSettingsProblem(Log.WARN,
7202 "Error in package manager settings: package "
7203 + name + " has bad sharedId " + sharedIdStr
7204 + " at " + parser.getPositionDescription());
7205 }
7206 } else {
7207 reportSettingsProblem(Log.WARN,
7208 "Error in package manager settings: package "
7209 + name + " has bad userId " + idStr + " at "
7210 + parser.getPositionDescription());
7211 }
7212 } catch (NumberFormatException e) {
7213 reportSettingsProblem(Log.WARN,
7214 "Error in package manager settings: package "
7215 + name + " has bad userId " + idStr + " at "
7216 + parser.getPositionDescription());
7217 }
7218 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007219 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007220 final String enabledStr = parser.getAttributeValue(null, "enabled");
7221 if (enabledStr != null) {
7222 if (enabledStr.equalsIgnoreCase("true")) {
7223 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7224 } else if (enabledStr.equalsIgnoreCase("false")) {
7225 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7226 } else if (enabledStr.equalsIgnoreCase("default")) {
7227 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7228 } else {
7229 reportSettingsProblem(Log.WARN,
7230 "Error in package manager settings: package "
7231 + name + " has bad enabled value: " + idStr
7232 + " at " + parser.getPositionDescription());
7233 }
7234 } else {
7235 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7236 }
7237 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7238 if (installStatusStr != null) {
7239 if (installStatusStr.equalsIgnoreCase("false")) {
7240 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7241 } else {
7242 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7243 }
7244 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007246 int outerDepth = parser.getDepth();
7247 int type;
7248 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7249 && (type != XmlPullParser.END_TAG
7250 || parser.getDepth() > outerDepth)) {
7251 if (type == XmlPullParser.END_TAG
7252 || type == XmlPullParser.TEXT) {
7253 continue;
7254 }
7255
7256 String tagName = parser.getName();
7257 if (tagName.equals("disabled-components")) {
7258 readDisabledComponentsLP(packageSetting, parser);
7259 } else if (tagName.equals("enabled-components")) {
7260 readEnabledComponentsLP(packageSetting, parser);
7261 } else if (tagName.equals("sigs")) {
7262 packageSetting.signatures.readXml(parser, mPastSignatures);
7263 } else if (tagName.equals("perms")) {
7264 readGrantedPermissionsLP(parser,
7265 packageSetting.loadedPermissions);
7266 packageSetting.permissionsFixed = true;
7267 } else {
7268 reportSettingsProblem(Log.WARN,
7269 "Unknown element under <package>: "
7270 + parser.getName());
7271 XmlUtils.skipCurrentTag(parser);
7272 }
7273 }
7274 } else {
7275 XmlUtils.skipCurrentTag(parser);
7276 }
7277 }
7278
7279 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7280 XmlPullParser parser)
7281 throws IOException, XmlPullParserException {
7282 int outerDepth = parser.getDepth();
7283 int type;
7284 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7285 && (type != XmlPullParser.END_TAG
7286 || parser.getDepth() > outerDepth)) {
7287 if (type == XmlPullParser.END_TAG
7288 || type == XmlPullParser.TEXT) {
7289 continue;
7290 }
7291
7292 String tagName = parser.getName();
7293 if (tagName.equals("item")) {
7294 String name = parser.getAttributeValue(null, "name");
7295 if (name != null) {
7296 packageSetting.disabledComponents.add(name.intern());
7297 } else {
7298 reportSettingsProblem(Log.WARN,
7299 "Error in package manager settings: <disabled-components> has"
7300 + " no name at " + parser.getPositionDescription());
7301 }
7302 } else {
7303 reportSettingsProblem(Log.WARN,
7304 "Unknown element under <disabled-components>: "
7305 + parser.getName());
7306 }
7307 XmlUtils.skipCurrentTag(parser);
7308 }
7309 }
7310
7311 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7312 XmlPullParser parser)
7313 throws IOException, XmlPullParserException {
7314 int outerDepth = parser.getDepth();
7315 int type;
7316 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7317 && (type != XmlPullParser.END_TAG
7318 || parser.getDepth() > outerDepth)) {
7319 if (type == XmlPullParser.END_TAG
7320 || type == XmlPullParser.TEXT) {
7321 continue;
7322 }
7323
7324 String tagName = parser.getName();
7325 if (tagName.equals("item")) {
7326 String name = parser.getAttributeValue(null, "name");
7327 if (name != null) {
7328 packageSetting.enabledComponents.add(name.intern());
7329 } else {
7330 reportSettingsProblem(Log.WARN,
7331 "Error in package manager settings: <enabled-components> has"
7332 + " no name at " + parser.getPositionDescription());
7333 }
7334 } else {
7335 reportSettingsProblem(Log.WARN,
7336 "Unknown element under <enabled-components>: "
7337 + parser.getName());
7338 }
7339 XmlUtils.skipCurrentTag(parser);
7340 }
7341 }
7342
7343 private void readSharedUserLP(XmlPullParser parser)
7344 throws XmlPullParserException, IOException {
7345 String name = null;
7346 String idStr = null;
7347 int pkgFlags = 0;
7348 SharedUserSetting su = null;
7349 try {
7350 name = parser.getAttributeValue(null, "name");
7351 idStr = parser.getAttributeValue(null, "userId");
7352 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7353 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7354 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7355 }
7356 if (name == null) {
7357 reportSettingsProblem(Log.WARN,
7358 "Error in package manager settings: <shared-user> has no name at "
7359 + parser.getPositionDescription());
7360 } else if (userId == 0) {
7361 reportSettingsProblem(Log.WARN,
7362 "Error in package manager settings: shared-user "
7363 + name + " has bad userId " + idStr + " at "
7364 + parser.getPositionDescription());
7365 } else {
7366 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7367 reportSettingsProblem(Log.ERROR,
7368 "Occurred while parsing settings at "
7369 + parser.getPositionDescription());
7370 }
7371 }
7372 } catch (NumberFormatException e) {
7373 reportSettingsProblem(Log.WARN,
7374 "Error in package manager settings: package "
7375 + name + " has bad userId " + idStr + " at "
7376 + parser.getPositionDescription());
7377 };
7378
7379 if (su != null) {
7380 int outerDepth = parser.getDepth();
7381 int type;
7382 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7383 && (type != XmlPullParser.END_TAG
7384 || parser.getDepth() > outerDepth)) {
7385 if (type == XmlPullParser.END_TAG
7386 || type == XmlPullParser.TEXT) {
7387 continue;
7388 }
7389
7390 String tagName = parser.getName();
7391 if (tagName.equals("sigs")) {
7392 su.signatures.readXml(parser, mPastSignatures);
7393 } else if (tagName.equals("perms")) {
7394 readGrantedPermissionsLP(parser, su.loadedPermissions);
7395 } else {
7396 reportSettingsProblem(Log.WARN,
7397 "Unknown element under <shared-user>: "
7398 + parser.getName());
7399 XmlUtils.skipCurrentTag(parser);
7400 }
7401 }
7402
7403 } else {
7404 XmlUtils.skipCurrentTag(parser);
7405 }
7406 }
7407
7408 private void readGrantedPermissionsLP(XmlPullParser parser,
7409 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7410 int outerDepth = parser.getDepth();
7411 int type;
7412 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7413 && (type != XmlPullParser.END_TAG
7414 || parser.getDepth() > outerDepth)) {
7415 if (type == XmlPullParser.END_TAG
7416 || type == XmlPullParser.TEXT) {
7417 continue;
7418 }
7419
7420 String tagName = parser.getName();
7421 if (tagName.equals("item")) {
7422 String name = parser.getAttributeValue(null, "name");
7423 if (name != null) {
7424 outPerms.add(name.intern());
7425 } else {
7426 reportSettingsProblem(Log.WARN,
7427 "Error in package manager settings: <perms> has"
7428 + " no name at " + parser.getPositionDescription());
7429 }
7430 } else {
7431 reportSettingsProblem(Log.WARN,
7432 "Unknown element under <perms>: "
7433 + parser.getName());
7434 }
7435 XmlUtils.skipCurrentTag(parser);
7436 }
7437 }
7438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 private void readPreferredActivitiesLP(XmlPullParser parser)
7440 throws XmlPullParserException, IOException {
7441 int outerDepth = parser.getDepth();
7442 int type;
7443 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7444 && (type != XmlPullParser.END_TAG
7445 || parser.getDepth() > outerDepth)) {
7446 if (type == XmlPullParser.END_TAG
7447 || type == XmlPullParser.TEXT) {
7448 continue;
7449 }
7450
7451 String tagName = parser.getName();
7452 if (tagName.equals("item")) {
7453 PreferredActivity pa = new PreferredActivity(parser);
7454 if (pa.mParseError == null) {
7455 mPreferredActivities.addFilter(pa);
7456 } else {
7457 reportSettingsProblem(Log.WARN,
7458 "Error in package manager settings: <preferred-activity> "
7459 + pa.mParseError + " at "
7460 + parser.getPositionDescription());
7461 }
7462 } else {
7463 reportSettingsProblem(Log.WARN,
7464 "Unknown element under <preferred-activities>: "
7465 + parser.getName());
7466 XmlUtils.skipCurrentTag(parser);
7467 }
7468 }
7469 }
7470
7471 // Returns -1 if we could not find an available UserId to assign
7472 private int newUserIdLP(Object obj) {
7473 // Let's be stupidly inefficient for now...
7474 final int N = mUserIds.size();
7475 for (int i=0; i<N; i++) {
7476 if (mUserIds.get(i) == null) {
7477 mUserIds.set(i, obj);
7478 return FIRST_APPLICATION_UID + i;
7479 }
7480 }
7481
7482 // None left?
7483 if (N >= MAX_APPLICATION_UIDS) {
7484 return -1;
7485 }
7486
7487 mUserIds.add(obj);
7488 return FIRST_APPLICATION_UID + N;
7489 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007491 public PackageSetting getDisabledSystemPkg(String name) {
7492 synchronized(mPackages) {
7493 PackageSetting ps = mDisabledSysPackages.get(name);
7494 return ps;
7495 }
7496 }
7497
7498 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7499 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7500 if (Config.LOGV) {
7501 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7502 + " componentName = " + componentInfo.name);
7503 Log.v(TAG, "enabledComponents: "
7504 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7505 Log.v(TAG, "disabledComponents: "
7506 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7507 }
7508 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7509 || ((componentInfo.enabled
7510 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7511 || (componentInfo.applicationInfo.enabled
7512 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7513 && !packageSettings.disabledComponents.contains(componentInfo.name))
7514 || packageSettings.enabledComponents.contains(componentInfo.name));
7515 }
7516 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007517
7518 // ------- apps on sdcard specific code -------
7519 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08007520 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08007521 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007522 private boolean mMediaMounted = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007523
7524 private MountService getMountService() {
7525 return (MountService) ServiceManager.getService("mount");
7526 }
7527
7528 private String createSdDir(File tmpPackageFile, String pkgName) {
7529 // Create mount point via MountService
7530 MountService mountService = getMountService();
7531 long len = tmpPackageFile.length();
7532 int mbLen = (int) (len/(1024*1024));
7533 if ((len - (mbLen * 1024 * 1024)) > 0) {
7534 mbLen++;
7535 }
7536 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
7537 String cachePath = null;
7538 // Remove any pending destroy messages
7539 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
Oscar Montemayord02546b2010-01-14 16:38:40 -08007540 String sdEncKey;
7541 try {
7542 sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7543 if (sdEncKey == null) {
7544 sdEncKey = SystemKeyStore.getInstance().
7545 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
7546 if (sdEncKey == null) {
7547 Log.e(TAG, "Failed to create encryption keys for package: " + pkgName + ".");
7548 return null;
7549 }
7550 }
7551 } catch (NoSuchAlgorithmException nsae) {
7552 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
7553 return null;
7554 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007555 try {
7556 cachePath = mountService.createSecureContainer(pkgName,
7557 mbLen,
Oscar Montemayord02546b2010-01-14 16:38:40 -08007558 "vfat", sdEncKey, Process.SYSTEM_UID);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007559 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
7560 return cachePath;
7561 } catch(IllegalStateException e) {
7562 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7563 }
7564 // TODO just fail here and let the user delete later on.
7565 try {
7566 mountService.destroySecureContainer(pkgName);
7567 if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
7568 } catch(IllegalStateException e) {
7569 Log.e(TAG, "Failed to destroy existing cache: " + e);
7570 return null;
7571 }
7572 try {
7573 cachePath = mountService.createSecureContainer(pkgName,
7574 mbLen,
Oscar Montemayord02546b2010-01-14 16:38:40 -08007575 "vfat", sdEncKey, Process.SYSTEM_UID);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007576 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
7577 return cachePath;
7578 } catch(IllegalStateException e) {
7579 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7580 return null;
7581 }
7582 }
7583
7584 private String mountSdDir(String pkgName, int ownerUid) {
Oscar Montemayord02546b2010-01-14 16:38:40 -08007585 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7586 if (sdEncKey == null) {
7587 Log.e(TAG, "Failed to retrieve encryption keys to mount package code: " + pkgName + ".");
7588 return null;
7589 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007590 try {
Oscar Montemayord02546b2010-01-14 16:38:40 -08007591 return getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007592 } catch (IllegalStateException e) {
7593 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
7594 }
7595 return null;
7596 }
7597
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007598 private boolean unMountSdDir(String pkgName) {
7599 // STOPSHIP unmount directory
7600 return true;
7601 }
7602
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007603 private String getSdDir(String pkgName) {
7604 String cachePath = null;
7605 try {
7606 cachePath = getMountService().getSecureContainerPath(pkgName);
7607 } catch (IllegalStateException e) {
7608 Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
7609 }
7610 return cachePath;
7611 }
7612
7613 private boolean finalizeSdDir(String pkgName) {
7614 try {
7615 getMountService().finalizeSecureContainer(pkgName);
7616 return true;
7617 } catch (IllegalStateException e) {
7618 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7619 return false;
7620 }
7621 }
7622
7623 private boolean destroySdDir(String pkgName) {
7624 try {
7625 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7626 // Don't have to send message again
7627 mHandler.removeMessages(DESTROY_SD_CONTAINER, pkgName);
7628 }
7629 // We need to destroy right away
7630 getMountService().destroySecureContainer(pkgName);
7631 return true;
7632 } catch (IllegalStateException e) {
7633 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
7634 return false;
7635 }
7636 }
7637
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007638 private String[] getSecureContainerList() {
7639 try {
7640 return getMountService().getSecureContainerList();
7641 } catch (IllegalStateException e) {
7642 Log.i(TAG, "Failed to getSecureContainerList");
7643 }
7644 return null;
7645 }
7646
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007647 private void sendDelayedDestroySdDir(String pkgName) {
7648 if (mHandler.hasMessages(DESTROY_SD_CONTAINER, pkgName)) {
7649 // Don't have to send message again
7650 return;
7651 }
7652 Message msg = mHandler.obtainMessage(DESTROY_SD_CONTAINER, pkgName);
7653 mHandler.sendMessageDelayed(msg, DESTROY_SD_CONTAINER_DELAY);
7654 }
7655
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007656 public void updateExternalMediaStatus(final boolean mediaStatus) {
7657 if (mediaStatus == mMediaMounted) {
7658 return;
7659 }
7660 mMediaMounted = mediaStatus;
7661 // Queue up an async operation since the package installation may take a little while.
7662 mHandler.post(new Runnable() {
7663 public void run() {
7664 mHandler.removeCallbacks(this);
7665 final String list[] = getSecureContainerList();
7666 if (list == null || list.length == 0) {
7667 return;
7668 }
7669 for (int i = 0; i < list.length; i++) {
7670 String mountPkg = list[i];
7671 // TODO compare with default package
7672 synchronized (mPackages) {
7673 PackageSetting ps = mSettings.mPackages.get(mountPkg);
7674 if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
7675 if (mediaStatus) {
7676 String pkgPath = getSdDir(mountPkg);
7677 if (pkgPath == null) {
7678 continue;
7679 }
7680 pkgPath = ps.codePathString;
7681 int parseFlags = PackageParser.PARSE_CHATTY |
7682 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
7683 PackageParser pp = new PackageParser(pkgPath);
7684 pp.setSeparateProcesses(mSeparateProcesses);
7685 final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
7686 null, mMetrics, parseFlags);
7687 if (pkg == null) {
7688 Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
7689 continue;
7690 }
7691 int scanMode = SCAN_MONITOR;
7692 // Scan the package
7693 if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
7694 // Grant permissions
7695 grantPermissionsLP(pkg, false);
7696 // Persist settings
7697 mSettings.writeLP();
7698 } else {
7699 Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
7700 }
7701 } else {
7702 // Delete package
7703 PackageRemovedInfo outInfo = new PackageRemovedInfo();
7704 boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
7705 if (!res) {
7706 Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
7707 }
7708 }
7709 }
7710 }
7711 }
7712 }
7713 });
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007715}