blob: 2b12268babbd67454d0407d98de66ce36b676de2 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import com.android.internal.app.ResolverActivity;
Tom Taylord4a47292009-12-21 13:59:18 -080020import com.android.common.FastXmlSerializer;
21import com.android.common.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
23import org.xmlpull.v1.XmlPullParser;
24import org.xmlpull.v1.XmlPullParserException;
25import org.xmlpull.v1.XmlSerializer;
26
27import android.app.ActivityManagerNative;
28import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.Context;
31import android.content.Intent;
32import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070033import android.content.IntentSender;
34import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.pm.ActivityInfo;
36import android.content.pm.ApplicationInfo;
37import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070038import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.content.pm.IPackageDataObserver;
40import android.content.pm.IPackageDeleteObserver;
41import android.content.pm.IPackageInstallObserver;
42import android.content.pm.IPackageManager;
43import android.content.pm.IPackageStatsObserver;
44import android.content.pm.InstrumentationInfo;
45import android.content.pm.PackageInfo;
46import android.content.pm.PackageManager;
47import android.content.pm.PackageStats;
48import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
49import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
50import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
51import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
52import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
53import android.content.pm.PackageParser;
54import android.content.pm.PermissionInfo;
55import android.content.pm.PermissionGroupInfo;
56import android.content.pm.ProviderInfo;
57import android.content.pm.ResolveInfo;
58import android.content.pm.ServiceInfo;
59import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.net.Uri;
61import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070062import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.Bundle;
64import android.os.HandlerThread;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070065import android.os.Looper;
66import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.Parcel;
68import android.os.RemoteException;
69import android.os.Environment;
70import android.os.FileObserver;
71import android.os.FileUtils;
72import android.os.Handler;
73import android.os.ParcelFileDescriptor;
74import android.os.Process;
75import android.os.ServiceManager;
76import android.os.SystemClock;
77import android.os.SystemProperties;
78import android.util.*;
79import android.view.Display;
80import android.view.WindowManager;
81
82import java.io.File;
83import java.io.FileDescriptor;
84import java.io.FileInputStream;
85import java.io.FileNotFoundException;
86import java.io.FileOutputStream;
87import java.io.FileReader;
88import java.io.FilenameFilter;
89import java.io.IOException;
90import java.io.InputStream;
91import java.io.PrintWriter;
92import java.util.ArrayList;
93import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -070094import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import java.util.Collections;
96import java.util.Comparator;
97import java.util.Enumeration;
98import java.util.HashMap;
99import java.util.HashSet;
100import java.util.Iterator;
101import java.util.List;
102import java.util.Map;
103import java.util.Set;
104import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800105import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.zip.ZipFile;
107import java.util.zip.ZipOutputStream;
108
109class PackageManagerService extends IPackageManager.Stub {
110 private static final String TAG = "PackageManager";
111 private static final boolean DEBUG_SETTINGS = false;
112 private static final boolean DEBUG_PREFERRED = false;
113
114 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
115 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400116 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 private static final int FIRST_APPLICATION_UID =
118 Process.FIRST_APPLICATION_UID;
119 private static final int MAX_APPLICATION_UIDS = 1000;
120
121 private static final boolean SHOW_INFO = false;
122
123 private static final boolean GET_CERTIFICATES = true;
124
Oscar Montemayora8529f62009-11-18 10:14:20 -0800125 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private static final int REMOVE_EVENTS =
128 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
129 private static final int ADD_EVENTS =
130 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
131
132 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
133
134 static final int SCAN_MONITOR = 1<<0;
135 static final int SCAN_NO_DEX = 1<<1;
136 static final int SCAN_FORCE_DEX = 1<<2;
137 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
138 static final int SCAN_FORWARD_LOCKED = 1<<4;
The Android Open Source Project10592532009-03-18 17:39:46 -0700139 static final int SCAN_NEW_INSTALL = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
142 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700143 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Dianne Hackborn851a5412009-05-08 12:06:44 -0700145 final int mSdkVersion = Build.VERSION.SDK_INT;
146 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
147 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 final Context mContext;
150 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700151 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 final DisplayMetrics mMetrics;
153 final int mDefParseFlags;
154 final String[] mSeparateProcesses;
155
156 // This is where all application persistent data goes.
157 final File mAppDataDir;
158
Oscar Montemayora8529f62009-11-18 10:14:20 -0800159 // If Encrypted File System feature is enabled, all application persistent data
160 // should go here instead.
161 final File mSecureAppDataDir;
162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 // This is the object monitoring the framework dir.
164 final FileObserver mFrameworkInstallObserver;
165
166 // This is the object monitoring the system app dir.
167 final FileObserver mSystemInstallObserver;
168
169 // This is the object monitoring mAppInstallDir.
170 final FileObserver mAppInstallObserver;
171
172 // This is the object monitoring mDrmAppPrivateInstallDir.
173 final FileObserver mDrmAppInstallObserver;
174
175 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
176 // LOCK HELD. Can be called with mInstallLock held.
177 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179 final File mFrameworkDir;
180 final File mSystemAppDir;
181 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700182 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183
184 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
185 // apps.
186 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // Lock for state used when installing and doing other long running
191 // operations. Methods that must be called with this lock held have
192 // the prefix "LI".
193 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 // These are the directories in the 3rd party applications installed dir
196 // that we have currently loaded packages from. Keys are the application's
197 // installed zip file (absolute codePath), and values are Package.
198 final HashMap<String, PackageParser.Package> mAppDirs =
199 new HashMap<String, PackageParser.Package>();
200
201 // Information for the parser to write more useful error messages.
202 File mScanningPath;
203 int mLastScanError;
204
205 final int[] mOutPermissions = new int[3];
206
207 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // Keys are String (package name), values are Package. This also serves
210 // as the lock for the global state. Methods that must be called with
211 // this lock held have the prefix "LP".
212 final HashMap<String, PackageParser.Package> mPackages =
213 new HashMap<String, PackageParser.Package>();
214
215 final Settings mSettings;
216 boolean mRestoredSettings;
217 boolean mReportedUidError;
218
219 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
220 int[] mGlobalGids;
221
222 // These are the built-in uid -> permission mappings that were read from the
223 // etc/permissions.xml file.
224 final SparseArray<HashSet<String>> mSystemPermissions =
225 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 // These are the built-in shared libraries that were read from the
228 // etc/permissions.xml file.
229 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800230
Dianne Hackborn49237342009-08-27 20:08:01 -0700231 // Temporary for building the final shared libraries for an .apk.
232 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800233
Dianne Hackborn49237342009-08-27 20:08:01 -0700234 // These are the features this devices supports that were read from the
235 // etc/permissions.xml file.
236 final HashMap<String, FeatureInfo> mAvailableFeatures =
237 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 // All available activities, for your resolving pleasure.
240 final ActivityIntentResolver mActivities =
241 new ActivityIntentResolver();
242
243 // All available receivers, for your resolving pleasure.
244 final ActivityIntentResolver mReceivers =
245 new ActivityIntentResolver();
246
247 // All available services, for your resolving pleasure.
248 final ServiceIntentResolver mServices = new ServiceIntentResolver();
249
250 // Keys are String (provider class name), values are Provider.
251 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
252 new HashMap<ComponentName, PackageParser.Provider>();
253
254 // Mapping from provider base names (first directory in content URI codePath)
255 // to the provider information.
256 final HashMap<String, PackageParser.Provider> mProviders =
257 new HashMap<String, PackageParser.Provider>();
258
259 // Mapping from instrumentation class names to info about them.
260 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
261 new HashMap<ComponentName, PackageParser.Instrumentation>();
262
263 // Mapping from permission names to info about them.
264 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
265 new HashMap<String, PackageParser.PermissionGroup>();
266
Dianne Hackborn854060af2009-07-09 18:14:31 -0700267 // Broadcast actions that are only available to the system.
268 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 boolean mSystemReady;
271 boolean mSafeMode;
272 boolean mHasSystemUidErrors;
273
274 ApplicationInfo mAndroidApplication;
275 final ActivityInfo mResolveActivity = new ActivityInfo();
276 final ResolveInfo mResolveInfo = new ResolveInfo();
277 ComponentName mResolveComponentName;
278 PackageParser.Package mPlatformPackage;
279
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700280 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800281 final HashMap<String, ArrayList<String>> mPendingBroadcasts
282 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700283 static final int SEND_PENDING_BROADCAST = 1;
284 // Delay time in millisecs
285 static final int BROADCAST_DELAY = 10 * 1000;
286
287 class PackageHandler extends Handler {
288 PackageHandler(Looper looper) {
289 super(looper);
290 }
291 public void handleMessage(Message msg) {
292 switch (msg.what) {
293 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800294 String packages[];
295 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700296 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700297 int uids[];
298 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800299 if (mPendingBroadcasts == null) {
300 return;
301 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700302 size = mPendingBroadcasts.size();
303 if (size <= 0) {
304 // Nothing to be done. Just return
305 return;
306 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800307 packages = new String[size];
308 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700309 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800310 Iterator<HashMap.Entry<String, ArrayList<String>>>
311 it = mPendingBroadcasts.entrySet().iterator();
312 int i = 0;
313 while (it.hasNext() && i < size) {
314 HashMap.Entry<String, ArrayList<String>> ent = it.next();
315 packages[i] = ent.getKey();
316 components[i] = ent.getValue();
317 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700318 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800319 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700320 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800321 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700322 mPendingBroadcasts.clear();
323 }
324 // Send broadcasts
325 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800326 sendPackageChangedBroadcast(packages[i], true,
327 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700328 }
329 break;
330 }
331 }
332 }
333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 public static final IPackageManager main(Context context, boolean factoryTest) {
335 PackageManagerService m = new PackageManagerService(context, factoryTest);
336 ServiceManager.addService("package", m);
337 return m;
338 }
339
340 static String[] splitString(String str, char sep) {
341 int count = 1;
342 int i = 0;
343 while ((i=str.indexOf(sep, i)) >= 0) {
344 count++;
345 i++;
346 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 String[] res = new String[count];
349 i=0;
350 count = 0;
351 int lastI=0;
352 while ((i=str.indexOf(sep, i)) >= 0) {
353 res[count] = str.substring(lastI, i);
354 count++;
355 i++;
356 lastI = i;
357 }
358 res[count] = str.substring(lastI, str.length());
359 return res;
360 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800363 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 if (mSdkVersion <= 0) {
367 Log.w(TAG, "**** ro.build.version.sdk not set!");
368 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 mContext = context;
371 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700372 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 mMetrics = new DisplayMetrics();
374 mSettings = new Settings();
375 mSettings.addSharedUserLP("android.uid.system",
376 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
377 mSettings.addSharedUserLP("android.uid.phone",
378 MULTIPLE_APPLICATION_UIDS
379 ? RADIO_UID : FIRST_APPLICATION_UID,
380 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400381 mSettings.addSharedUserLP("android.uid.log",
382 MULTIPLE_APPLICATION_UIDS
383 ? LOG_UID : FIRST_APPLICATION_UID,
384 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
386 String separateProcesses = SystemProperties.get("debug.separate_processes");
387 if (separateProcesses != null && separateProcesses.length() > 0) {
388 if ("*".equals(separateProcesses)) {
389 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
390 mSeparateProcesses = null;
391 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
392 } else {
393 mDefParseFlags = 0;
394 mSeparateProcesses = separateProcesses.split(",");
395 Log.w(TAG, "Running with debug.separate_processes: "
396 + separateProcesses);
397 }
398 } else {
399 mDefParseFlags = 0;
400 mSeparateProcesses = null;
401 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 Installer installer = new Installer();
404 // Little hacky thing to check if installd is here, to determine
405 // whether we are running on the simulator and thus need to take
406 // care of building the /data file structure ourself.
407 // (apparently the sim now has a working installer)
408 if (installer.ping() && Process.supportsProcesses()) {
409 mInstaller = installer;
410 } else {
411 mInstaller = null;
412 }
413
414 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
415 Display d = wm.getDefaultDisplay();
416 d.getMetrics(mMetrics);
417
418 synchronized (mInstallLock) {
419 synchronized (mPackages) {
420 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700421 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 File dataDir = Environment.getDataDirectory();
424 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800425 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
427
428 if (mInstaller == null) {
429 // Make sure these dirs exist, when we are running in
430 // the simulator.
431 // Make a wide-open directory for random misc stuff.
432 File miscDir = new File(dataDir, "misc");
433 miscDir.mkdirs();
434 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800435 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 mDrmAppPrivateInstallDir.mkdirs();
437 }
438
439 readPermissions();
440
441 mRestoredSettings = mSettings.readLP();
442 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800443
444 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700448 if (mNoDexOpt) {
449 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800450 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700451 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700456 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700459 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 /**
462 * Out of paranoia, ensure that everything in the boot class
463 * path has been dexed.
464 */
465 String bootClassPath = System.getProperty("java.boot.class.path");
466 if (bootClassPath != null) {
467 String[] paths = splitString(bootClassPath, ':');
468 for (int i=0; i<paths.length; i++) {
469 try {
470 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
471 libFiles.add(paths[i]);
472 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700473 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 }
475 } catch (FileNotFoundException e) {
476 Log.w(TAG, "Boot class path not found: " + paths[i]);
477 } catch (IOException e) {
478 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
479 }
480 }
481 } else {
482 Log.w(TAG, "No BOOTCLASSPATH found!");
483 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 /**
486 * Also ensure all external libraries have had dexopt run on them.
487 */
488 if (mSharedLibraries.size() > 0) {
489 Iterator<String> libs = mSharedLibraries.values().iterator();
490 while (libs.hasNext()) {
491 String lib = libs.next();
492 try {
493 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
494 libFiles.add(lib);
495 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700496 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
498 } catch (FileNotFoundException e) {
499 Log.w(TAG, "Library not found: " + lib);
500 } catch (IOException e) {
501 Log.w(TAG, "Exception reading library: " + lib, e);
502 }
503 }
504 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 // Gross hack for now: we know this file doesn't contain any
507 // code, so don't dexopt it to avoid the resulting log spew.
508 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 /**
511 * And there are a number of commands implemented in Java, which
512 * we currently need to do the dexopt on so that they can be
513 * run from a non-root shell.
514 */
515 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700516 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 for (int i=0; i<frameworkFiles.length; i++) {
518 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
519 String path = libPath.getPath();
520 // Skip the file if we alrady did it.
521 if (libFiles.contains(path)) {
522 continue;
523 }
524 // Skip the file if it is not a type we want to dexopt.
525 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
526 continue;
527 }
528 try {
529 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
530 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700531 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 }
533 } catch (FileNotFoundException e) {
534 Log.w(TAG, "Jar not found: " + path);
535 } catch (IOException e) {
536 Log.w(TAG, "Exception reading jar: " + path, e);
537 }
538 }
539 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800540
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700541 if (didDexOpt) {
542 // If we had to do a dexopt of one of the previous
543 // things, then something on the system has changed.
544 // Consider this significant, and wipe away all other
545 // existing dexopt files to ensure we don't leave any
546 // dangling around.
547 String[] files = mDalvikCacheDir.list();
548 if (files != null) {
549 for (int i=0; i<files.length; i++) {
550 String fn = files[i];
551 if (fn.startsWith("data@app@")
552 || fn.startsWith("data@app-private@")) {
553 Log.i(TAG, "Pruning dalvik file: " + fn);
554 (new File(mDalvikCacheDir, fn)).delete();
555 }
556 }
557 }
558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 mFrameworkInstallObserver = new AppDirObserver(
562 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
563 mFrameworkInstallObserver.startWatching();
564 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
565 scanMode | SCAN_NO_DEX);
566 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
567 mSystemInstallObserver = new AppDirObserver(
568 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
569 mSystemInstallObserver.startWatching();
570 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
571 mAppInstallDir = new File(dataDir, "app");
572 if (mInstaller == null) {
573 // Make sure these dirs exist, when we are running in
574 // the simulator.
575 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
576 }
577 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800578 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579 //clean up list
580 for(int i = 0; i < deletePkgsList.size(); i++) {
581 //clean up here
582 cleanupInstallFailedPackage(deletePkgsList.get(i));
583 }
584 //delete tmp files
585 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800586
587 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 SystemClock.uptimeMillis());
589 mAppInstallObserver = new AppDirObserver(
590 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
591 mAppInstallObserver.startWatching();
592 scanDirLI(mAppInstallDir, 0, scanMode);
593
594 mDrmAppInstallObserver = new AppDirObserver(
595 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
596 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -0700597 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800599 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 SystemClock.uptimeMillis());
601 Log.i(TAG, "Time to scan packages: "
602 + ((SystemClock.uptimeMillis()-startTime)/1000f)
603 + " seconds");
604
605 updatePermissionsLP();
606
607 mSettings.writeLP();
608
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800609 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 // Now after opening every single application zip, make sure they
613 // are all flushed. Not really needed, but keeps things nice and
614 // tidy.
615 Runtime.getRuntime().gc();
616 } // synchronized (mPackages)
617 } // synchronized (mInstallLock)
618 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 @Override
621 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
622 throws RemoteException {
623 try {
624 return super.onTransact(code, data, reply, flags);
625 } catch (RuntimeException e) {
626 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
627 Log.e(TAG, "Package Manager Crash", e);
628 }
629 throw e;
630 }
631 }
632
Oscar Montemayora8529f62009-11-18 10:14:20 -0800633 void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800635 boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
636 int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 if (retCode < 0) {
638 Log.w(TAG, "Couldn't remove app data directory for package: "
Oscar Montemayora8529f62009-11-18 10:14:20 -0800639 + pkgSettings.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 }
641 } else {
642 //for emulator
Oscar Montemayora8529f62009-11-18 10:14:20 -0800643 File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 dataDir.delete();
645 }
Oscar Montemayora8529f62009-11-18 10:14:20 -0800646 mSettings.removePackageLP(pkgSettings.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 }
648
649 void readPermissions() {
650 // Read permissions from .../etc/permission directory.
651 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
652 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
653 Log.w(TAG, "No directory " + libraryDir + ", skipping");
654 return;
655 }
656 if (!libraryDir.canRead()) {
657 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
658 return;
659 }
660
661 // Iterate over the files in the directory and scan .xml files
662 for (File f : libraryDir.listFiles()) {
663 // We'll read platform.xml last
664 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
665 continue;
666 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 if (!f.getPath().endsWith(".xml")) {
669 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
670 continue;
671 }
672 if (!f.canRead()) {
673 Log.w(TAG, "Permissions library file " + f + " cannot be read");
674 continue;
675 }
676
677 readPermissionsFromXml(f);
678 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
681 final File permFile = new File(Environment.getRootDirectory(),
682 "etc/permissions/platform.xml");
683 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800684
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700685 StringBuilder sb = new StringBuilder(128);
686 sb.append("Libs:");
687 Iterator<String> it = mSharedLibraries.keySet().iterator();
688 while (it.hasNext()) {
689 sb.append(' ');
690 String name = it.next();
691 sb.append(name);
692 sb.append(':');
693 sb.append(mSharedLibraries.get(name));
694 }
695 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800696
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700697 sb.setLength(0);
698 sb.append("Features:");
699 it = mAvailableFeatures.keySet().iterator();
700 while (it.hasNext()) {
701 sb.append(' ');
702 sb.append(it.next());
703 }
704 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800706
707 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 FileReader permReader = null;
709 try {
710 permReader = new FileReader(permFile);
711 } catch (FileNotFoundException e) {
712 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
713 return;
714 }
715
716 try {
717 XmlPullParser parser = Xml.newPullParser();
718 parser.setInput(permReader);
719
720 XmlUtils.beginDocument(parser, "permissions");
721
722 while (true) {
723 XmlUtils.nextElement(parser);
724 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
725 break;
726 }
727
728 String name = parser.getName();
729 if ("group".equals(name)) {
730 String gidStr = parser.getAttributeValue(null, "gid");
731 if (gidStr != null) {
732 int gid = Integer.parseInt(gidStr);
733 mGlobalGids = appendInt(mGlobalGids, gid);
734 } else {
735 Log.w(TAG, "<group> without gid at "
736 + parser.getPositionDescription());
737 }
738
739 XmlUtils.skipCurrentTag(parser);
740 continue;
741 } else if ("permission".equals(name)) {
742 String perm = parser.getAttributeValue(null, "name");
743 if (perm == null) {
744 Log.w(TAG, "<permission> without name at "
745 + parser.getPositionDescription());
746 XmlUtils.skipCurrentTag(parser);
747 continue;
748 }
749 perm = perm.intern();
750 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 } else if ("assign-permission".equals(name)) {
753 String perm = parser.getAttributeValue(null, "name");
754 if (perm == null) {
755 Log.w(TAG, "<assign-permission> without name at "
756 + parser.getPositionDescription());
757 XmlUtils.skipCurrentTag(parser);
758 continue;
759 }
760 String uidStr = parser.getAttributeValue(null, "uid");
761 if (uidStr == null) {
762 Log.w(TAG, "<assign-permission> without uid at "
763 + parser.getPositionDescription());
764 XmlUtils.skipCurrentTag(parser);
765 continue;
766 }
767 int uid = Process.getUidForName(uidStr);
768 if (uid < 0) {
769 Log.w(TAG, "<assign-permission> with unknown uid \""
770 + uidStr + "\" at "
771 + parser.getPositionDescription());
772 XmlUtils.skipCurrentTag(parser);
773 continue;
774 }
775 perm = perm.intern();
776 HashSet<String> perms = mSystemPermissions.get(uid);
777 if (perms == null) {
778 perms = new HashSet<String>();
779 mSystemPermissions.put(uid, perms);
780 }
781 perms.add(perm);
782 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 } else if ("library".equals(name)) {
785 String lname = parser.getAttributeValue(null, "name");
786 String lfile = parser.getAttributeValue(null, "file");
787 if (lname == null) {
788 Log.w(TAG, "<library> without name at "
789 + parser.getPositionDescription());
790 } else if (lfile == null) {
791 Log.w(TAG, "<library> without file at "
792 + parser.getPositionDescription());
793 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700794 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700795 mSharedLibraries.put(lname, lfile);
796 }
797 XmlUtils.skipCurrentTag(parser);
798 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800799
Dianne Hackborn49237342009-08-27 20:08:01 -0700800 } else if ("feature".equals(name)) {
801 String fname = parser.getAttributeValue(null, "name");
802 if (fname == null) {
803 Log.w(TAG, "<feature> without name at "
804 + parser.getPositionDescription());
805 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700806 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700807 FeatureInfo fi = new FeatureInfo();
808 fi.name = fname;
809 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 }
811 XmlUtils.skipCurrentTag(parser);
812 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 } else {
815 XmlUtils.skipCurrentTag(parser);
816 continue;
817 }
818
819 }
820 } catch (XmlPullParserException e) {
821 Log.w(TAG, "Got execption parsing permissions.", e);
822 } catch (IOException e) {
823 Log.w(TAG, "Got execption parsing permissions.", e);
824 }
825 }
826
827 void readPermission(XmlPullParser parser, String name)
828 throws IOException, XmlPullParserException {
829
830 name = name.intern();
831
832 BasePermission bp = mSettings.mPermissions.get(name);
833 if (bp == null) {
834 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
835 mSettings.mPermissions.put(name, bp);
836 }
837 int outerDepth = parser.getDepth();
838 int type;
839 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
840 && (type != XmlPullParser.END_TAG
841 || parser.getDepth() > outerDepth)) {
842 if (type == XmlPullParser.END_TAG
843 || type == XmlPullParser.TEXT) {
844 continue;
845 }
846
847 String tagName = parser.getName();
848 if ("group".equals(tagName)) {
849 String gidStr = parser.getAttributeValue(null, "gid");
850 if (gidStr != null) {
851 int gid = Process.getGidForName(gidStr);
852 bp.gids = appendInt(bp.gids, gid);
853 } else {
854 Log.w(TAG, "<group> without gid at "
855 + parser.getPositionDescription());
856 }
857 }
858 XmlUtils.skipCurrentTag(parser);
859 }
860 }
861
862 static int[] appendInt(int[] cur, int val) {
863 if (cur == null) {
864 return new int[] { val };
865 }
866 final int N = cur.length;
867 for (int i=0; i<N; i++) {
868 if (cur[i] == val) {
869 return cur;
870 }
871 }
872 int[] ret = new int[N+1];
873 System.arraycopy(cur, 0, ret, 0, N);
874 ret[N] = val;
875 return ret;
876 }
877
878 static int[] appendInts(int[] cur, int[] add) {
879 if (add == null) return cur;
880 if (cur == null) return add;
881 final int N = add.length;
882 for (int i=0; i<N; i++) {
883 cur = appendInt(cur, add[i]);
884 }
885 return cur;
886 }
887
888 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700889 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
890 // The package has been uninstalled but has retained data and resources.
891 return PackageParser.generatePackageInfo(p, null, flags);
892 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 final PackageSetting ps = (PackageSetting)p.mExtras;
894 if (ps == null) {
895 return null;
896 }
897 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
898 return PackageParser.generatePackageInfo(p, gp.gids, flags);
899 }
900
901 public PackageInfo getPackageInfo(String packageName, int flags) {
902 synchronized (mPackages) {
903 PackageParser.Package p = mPackages.get(packageName);
904 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700905 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 + ": " + p);
907 if (p != null) {
908 return generatePackageInfo(p, flags);
909 }
910 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
911 return generatePackageInfoFromSettingsLP(packageName, flags);
912 }
913 }
914 return null;
915 }
916
917 public int getPackageUid(String packageName) {
918 synchronized (mPackages) {
919 PackageParser.Package p = mPackages.get(packageName);
920 if(p != null) {
921 return p.applicationInfo.uid;
922 }
923 PackageSetting ps = mSettings.mPackages.get(packageName);
924 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
925 return -1;
926 }
927 p = ps.pkg;
928 return p != null ? p.applicationInfo.uid : -1;
929 }
930 }
931
932 public int[] getPackageGids(String packageName) {
933 synchronized (mPackages) {
934 PackageParser.Package p = mPackages.get(packageName);
935 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700936 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 + ": " + p);
938 if (p != null) {
939 final PackageSetting ps = (PackageSetting)p.mExtras;
940 final SharedUserSetting suid = ps.sharedUser;
941 return suid != null ? suid.gids : ps.gids;
942 }
943 }
944 // stupid thing to indicate an error.
945 return new int[0];
946 }
947
948 public PermissionInfo getPermissionInfo(String name, int flags) {
949 synchronized (mPackages) {
950 final BasePermission p = mSettings.mPermissions.get(name);
951 if (p != null && p.perm != null) {
952 return PackageParser.generatePermissionInfo(p.perm, flags);
953 }
954 return null;
955 }
956 }
957
958 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
959 synchronized (mPackages) {
960 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
961 for (BasePermission p : mSettings.mPermissions.values()) {
962 if (group == null) {
963 if (p.perm.info.group == null) {
964 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
965 }
966 } else {
967 if (group.equals(p.perm.info.group)) {
968 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
969 }
970 }
971 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 if (out.size() > 0) {
974 return out;
975 }
976 return mPermissionGroups.containsKey(group) ? out : null;
977 }
978 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
981 synchronized (mPackages) {
982 return PackageParser.generatePermissionGroupInfo(
983 mPermissionGroups.get(name), flags);
984 }
985 }
986
987 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
988 synchronized (mPackages) {
989 final int N = mPermissionGroups.size();
990 ArrayList<PermissionGroupInfo> out
991 = new ArrayList<PermissionGroupInfo>(N);
992 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
993 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
994 }
995 return out;
996 }
997 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1000 PackageSetting ps = mSettings.mPackages.get(packageName);
1001 if(ps != null) {
1002 if(ps.pkg == null) {
1003 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1004 if(pInfo != null) {
1005 return pInfo.applicationInfo;
1006 }
1007 return null;
1008 }
1009 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1010 }
1011 return null;
1012 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1015 PackageSetting ps = mSettings.mPackages.get(packageName);
1016 if(ps != null) {
1017 if(ps.pkg == null) {
1018 ps.pkg = new PackageParser.Package(packageName);
1019 ps.pkg.applicationInfo.packageName = packageName;
1020 }
1021 return generatePackageInfo(ps.pkg, flags);
1022 }
1023 return null;
1024 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1027 synchronized (mPackages) {
1028 PackageParser.Package p = mPackages.get(packageName);
1029 if (Config.LOGV) Log.v(
1030 TAG, "getApplicationInfo " + packageName
1031 + ": " + p);
1032 if (p != null) {
1033 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001034 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 }
1036 if ("android".equals(packageName)||"system".equals(packageName)) {
1037 return mAndroidApplication;
1038 }
1039 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1040 return generateApplicationInfoFromSettingsLP(packageName, flags);
1041 }
1042 }
1043 return null;
1044 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001045
1046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1048 mContext.enforceCallingOrSelfPermission(
1049 android.Manifest.permission.CLEAR_APP_CACHE, null);
1050 // Queue up an async operation since clearing cache may take a little while.
1051 mHandler.post(new Runnable() {
1052 public void run() {
1053 mHandler.removeCallbacks(this);
1054 int retCode = -1;
1055 if (mInstaller != null) {
1056 retCode = mInstaller.freeCache(freeStorageSize);
1057 if (retCode < 0) {
1058 Log.w(TAG, "Couldn't clear application caches");
1059 }
1060 } //end if mInstaller
1061 if (observer != null) {
1062 try {
1063 observer.onRemoveCompleted(null, (retCode >= 0));
1064 } catch (RemoteException e) {
1065 Log.w(TAG, "RemoveException when invoking call back");
1066 }
1067 }
1068 }
1069 });
1070 }
1071
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001072 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001073 mContext.enforceCallingOrSelfPermission(
1074 android.Manifest.permission.CLEAR_APP_CACHE, null);
1075 // Queue up an async operation since clearing cache may take a little while.
1076 mHandler.post(new Runnable() {
1077 public void run() {
1078 mHandler.removeCallbacks(this);
1079 int retCode = -1;
1080 if (mInstaller != null) {
1081 retCode = mInstaller.freeCache(freeStorageSize);
1082 if (retCode < 0) {
1083 Log.w(TAG, "Couldn't clear application caches");
1084 }
1085 }
1086 if(pi != null) {
1087 try {
1088 // Callback via pending intent
1089 int code = (retCode >= 0) ? 1 : 0;
1090 pi.sendIntent(null, code, null,
1091 null, null);
1092 } catch (SendIntentException e1) {
1093 Log.i(TAG, "Failed to send pending intent");
1094 }
1095 }
1096 }
1097 });
1098 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1101 synchronized (mPackages) {
1102 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001103
1104 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001106 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 }
1108 if (mResolveComponentName.equals(component)) {
1109 return mResolveActivity;
1110 }
1111 }
1112 return null;
1113 }
1114
1115 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1116 synchronized (mPackages) {
1117 PackageParser.Activity a = mReceivers.mActivities.get(component);
1118 if (Config.LOGV) Log.v(
1119 TAG, "getReceiverInfo " + component + ": " + a);
1120 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1121 return PackageParser.generateActivityInfo(a, flags);
1122 }
1123 }
1124 return null;
1125 }
1126
1127 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1128 synchronized (mPackages) {
1129 PackageParser.Service s = mServices.mServices.get(component);
1130 if (Config.LOGV) Log.v(
1131 TAG, "getServiceInfo " + component + ": " + s);
1132 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1133 return PackageParser.generateServiceInfo(s, flags);
1134 }
1135 }
1136 return null;
1137 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 public String[] getSystemSharedLibraryNames() {
1140 Set<String> libSet;
1141 synchronized (mPackages) {
1142 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001143 int size = libSet.size();
1144 if (size > 0) {
1145 String[] libs = new String[size];
1146 libSet.toArray(libs);
1147 return libs;
1148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001150 return null;
1151 }
1152
1153 public FeatureInfo[] getSystemAvailableFeatures() {
1154 Collection<FeatureInfo> featSet;
1155 synchronized (mPackages) {
1156 featSet = mAvailableFeatures.values();
1157 int size = featSet.size();
1158 if (size > 0) {
1159 FeatureInfo[] features = new FeatureInfo[size+1];
1160 featSet.toArray(features);
1161 FeatureInfo fi = new FeatureInfo();
1162 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1163 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1164 features[size] = fi;
1165 return features;
1166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 }
1168 return null;
1169 }
1170
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001171 public boolean hasSystemFeature(String name) {
1172 synchronized (mPackages) {
1173 return mAvailableFeatures.containsKey(name);
1174 }
1175 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 public int checkPermission(String permName, String pkgName) {
1178 synchronized (mPackages) {
1179 PackageParser.Package p = mPackages.get(pkgName);
1180 if (p != null && p.mExtras != null) {
1181 PackageSetting ps = (PackageSetting)p.mExtras;
1182 if (ps.sharedUser != null) {
1183 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1184 return PackageManager.PERMISSION_GRANTED;
1185 }
1186 } else if (ps.grantedPermissions.contains(permName)) {
1187 return PackageManager.PERMISSION_GRANTED;
1188 }
1189 }
1190 }
1191 return PackageManager.PERMISSION_DENIED;
1192 }
1193
1194 public int checkUidPermission(String permName, int uid) {
1195 synchronized (mPackages) {
1196 Object obj = mSettings.getUserIdLP(uid);
1197 if (obj != null) {
1198 if (obj instanceof SharedUserSetting) {
1199 SharedUserSetting sus = (SharedUserSetting)obj;
1200 if (sus.grantedPermissions.contains(permName)) {
1201 return PackageManager.PERMISSION_GRANTED;
1202 }
1203 } else if (obj instanceof PackageSetting) {
1204 PackageSetting ps = (PackageSetting)obj;
1205 if (ps.grantedPermissions.contains(permName)) {
1206 return PackageManager.PERMISSION_GRANTED;
1207 }
1208 }
1209 } else {
1210 HashSet<String> perms = mSystemPermissions.get(uid);
1211 if (perms != null && perms.contains(permName)) {
1212 return PackageManager.PERMISSION_GRANTED;
1213 }
1214 }
1215 }
1216 return PackageManager.PERMISSION_DENIED;
1217 }
1218
1219 private BasePermission findPermissionTreeLP(String permName) {
1220 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1221 if (permName.startsWith(bp.name) &&
1222 permName.length() > bp.name.length() &&
1223 permName.charAt(bp.name.length()) == '.') {
1224 return bp;
1225 }
1226 }
1227 return null;
1228 }
1229
1230 private BasePermission checkPermissionTreeLP(String permName) {
1231 if (permName != null) {
1232 BasePermission bp = findPermissionTreeLP(permName);
1233 if (bp != null) {
1234 if (bp.uid == Binder.getCallingUid()) {
1235 return bp;
1236 }
1237 throw new SecurityException("Calling uid "
1238 + Binder.getCallingUid()
1239 + " is not allowed to add to permission tree "
1240 + bp.name + " owned by uid " + bp.uid);
1241 }
1242 }
1243 throw new SecurityException("No permission tree found for " + permName);
1244 }
1245
1246 public boolean addPermission(PermissionInfo info) {
1247 synchronized (mPackages) {
1248 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1249 throw new SecurityException("Label must be specified in permission");
1250 }
1251 BasePermission tree = checkPermissionTreeLP(info.name);
1252 BasePermission bp = mSettings.mPermissions.get(info.name);
1253 boolean added = bp == null;
1254 if (added) {
1255 bp = new BasePermission(info.name, tree.sourcePackage,
1256 BasePermission.TYPE_DYNAMIC);
1257 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1258 throw new SecurityException(
1259 "Not allowed to modify non-dynamic permission "
1260 + info.name);
1261 }
1262 bp.perm = new PackageParser.Permission(tree.perm.owner,
1263 new PermissionInfo(info));
1264 bp.perm.info.packageName = tree.perm.info.packageName;
1265 bp.uid = tree.uid;
1266 if (added) {
1267 mSettings.mPermissions.put(info.name, bp);
1268 }
1269 mSettings.writeLP();
1270 return added;
1271 }
1272 }
1273
1274 public void removePermission(String name) {
1275 synchronized (mPackages) {
1276 checkPermissionTreeLP(name);
1277 BasePermission bp = mSettings.mPermissions.get(name);
1278 if (bp != null) {
1279 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1280 throw new SecurityException(
1281 "Not allowed to modify non-dynamic permission "
1282 + name);
1283 }
1284 mSettings.mPermissions.remove(name);
1285 mSettings.writeLP();
1286 }
1287 }
1288 }
1289
Dianne Hackborn854060af2009-07-09 18:14:31 -07001290 public boolean isProtectedBroadcast(String actionName) {
1291 synchronized (mPackages) {
1292 return mProtectedBroadcasts.contains(actionName);
1293 }
1294 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 public int checkSignatures(String pkg1, String pkg2) {
1297 synchronized (mPackages) {
1298 PackageParser.Package p1 = mPackages.get(pkg1);
1299 PackageParser.Package p2 = mPackages.get(pkg2);
1300 if (p1 == null || p1.mExtras == null
1301 || p2 == null || p2.mExtras == null) {
1302 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1303 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001304 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305 }
1306 }
1307
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001308 public int checkUidSignatures(int uid1, int uid2) {
1309 synchronized (mPackages) {
1310 Signature[] s1;
1311 Signature[] s2;
1312 Object obj = mSettings.getUserIdLP(uid1);
1313 if (obj != null) {
1314 if (obj instanceof SharedUserSetting) {
1315 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1316 } else if (obj instanceof PackageSetting) {
1317 s1 = ((PackageSetting)obj).signatures.mSignatures;
1318 } else {
1319 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1320 }
1321 } else {
1322 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1323 }
1324 obj = mSettings.getUserIdLP(uid2);
1325 if (obj != null) {
1326 if (obj instanceof SharedUserSetting) {
1327 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1328 } else if (obj instanceof PackageSetting) {
1329 s2 = ((PackageSetting)obj).signatures.mSignatures;
1330 } else {
1331 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1332 }
1333 } else {
1334 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1335 }
1336 return checkSignaturesLP(s1, s2);
1337 }
1338 }
1339
1340 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1341 if (s1 == null) {
1342 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1344 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1345 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001346 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1348 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001349 final int N1 = s1.length;
1350 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 for (int i=0; i<N1; i++) {
1352 boolean match = false;
1353 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001354 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 match = true;
1356 break;
1357 }
1358 }
1359 if (!match) {
1360 return PackageManager.SIGNATURE_NO_MATCH;
1361 }
1362 }
1363 return PackageManager.SIGNATURE_MATCH;
1364 }
1365
1366 public String[] getPackagesForUid(int uid) {
1367 synchronized (mPackages) {
1368 Object obj = mSettings.getUserIdLP(uid);
1369 if (obj instanceof SharedUserSetting) {
1370 SharedUserSetting sus = (SharedUserSetting)obj;
1371 final int N = sus.packages.size();
1372 String[] res = new String[N];
1373 Iterator<PackageSetting> it = sus.packages.iterator();
1374 int i=0;
1375 while (it.hasNext()) {
1376 res[i++] = it.next().name;
1377 }
1378 return res;
1379 } else if (obj instanceof PackageSetting) {
1380 PackageSetting ps = (PackageSetting)obj;
1381 return new String[] { ps.name };
1382 }
1383 }
1384 return null;
1385 }
1386
1387 public String getNameForUid(int uid) {
1388 synchronized (mPackages) {
1389 Object obj = mSettings.getUserIdLP(uid);
1390 if (obj instanceof SharedUserSetting) {
1391 SharedUserSetting sus = (SharedUserSetting)obj;
1392 return sus.name + ":" + sus.userId;
1393 } else if (obj instanceof PackageSetting) {
1394 PackageSetting ps = (PackageSetting)obj;
1395 return ps.name;
1396 }
1397 }
1398 return null;
1399 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 public int getUidForSharedUser(String sharedUserName) {
1402 if(sharedUserName == null) {
1403 return -1;
1404 }
1405 synchronized (mPackages) {
1406 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1407 if(suid == null) {
1408 return -1;
1409 }
1410 return suid.userId;
1411 }
1412 }
1413
1414 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1415 int flags) {
1416 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001417 return chooseBestActivity(intent, resolvedType, flags, query);
1418 }
1419
Mihai Predaeae850c2009-05-13 10:13:48 +02001420 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1421 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001422 if (query != null) {
1423 final int N = query.size();
1424 if (N == 1) {
1425 return query.get(0);
1426 } else if (N > 1) {
1427 // If there is more than one activity with the same priority,
1428 // then let the user decide between them.
1429 ResolveInfo r0 = query.get(0);
1430 ResolveInfo r1 = query.get(1);
1431 if (false) {
1432 System.out.println(r0.activityInfo.name +
1433 "=" + r0.priority + " vs " +
1434 r1.activityInfo.name +
1435 "=" + r1.priority);
1436 }
1437 // If the first activity has a higher priority, or a different
1438 // default, then it is always desireable to pick it.
1439 if (r0.priority != r1.priority
1440 || r0.preferredOrder != r1.preferredOrder
1441 || r0.isDefault != r1.isDefault) {
1442 return query.get(0);
1443 }
1444 // If we have saved a preference for a preferred activity for
1445 // this Intent, use that.
1446 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1447 flags, query, r0.priority);
1448 if (ri != null) {
1449 return ri;
1450 }
1451 return mResolveInfo;
1452 }
1453 }
1454 return null;
1455 }
1456
1457 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1458 int flags, List<ResolveInfo> query, int priority) {
1459 synchronized (mPackages) {
1460 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1461 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001462 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1464 if (prefs != null && prefs.size() > 0) {
1465 // First figure out how good the original match set is.
1466 // We will only allow preferred activities that came
1467 // from the same match quality.
1468 int match = 0;
1469 final int N = query.size();
1470 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1471 for (int j=0; j<N; j++) {
1472 ResolveInfo ri = query.get(j);
1473 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1474 + ": 0x" + Integer.toHexString(match));
1475 if (ri.match > match) match = ri.match;
1476 }
1477 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1478 + Integer.toHexString(match));
1479 match &= IntentFilter.MATCH_CATEGORY_MASK;
1480 final int M = prefs.size();
1481 for (int i=0; i<M; i++) {
1482 PreferredActivity pa = prefs.get(i);
1483 if (pa.mMatch != match) {
1484 continue;
1485 }
1486 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1487 if (DEBUG_PREFERRED) {
1488 Log.v(TAG, "Got preferred activity:");
1489 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1490 }
1491 if (ai != null) {
1492 for (int j=0; j<N; j++) {
1493 ResolveInfo ri = query.get(j);
1494 if (!ri.activityInfo.applicationInfo.packageName
1495 .equals(ai.applicationInfo.packageName)) {
1496 continue;
1497 }
1498 if (!ri.activityInfo.name.equals(ai.name)) {
1499 continue;
1500 }
1501
1502 // Okay we found a previously set preferred app.
1503 // If the result set is different from when this
1504 // was created, we need to clear it and re-ask the
1505 // user their preference.
1506 if (!pa.sameSet(query, priority)) {
1507 Log.i(TAG, "Result set changed, dropping preferred activity for "
1508 + intent + " type " + resolvedType);
1509 mSettings.mPreferredActivities.removeFilter(pa);
1510 return null;
1511 }
1512
1513 // Yay!
1514 return ri;
1515 }
1516 }
1517 }
1518 }
1519 }
1520 return null;
1521 }
1522
1523 public List<ResolveInfo> queryIntentActivities(Intent intent,
1524 String resolvedType, int flags) {
1525 ComponentName comp = intent.getComponent();
1526 if (comp != null) {
1527 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1528 ActivityInfo ai = getActivityInfo(comp, flags);
1529 if (ai != null) {
1530 ResolveInfo ri = new ResolveInfo();
1531 ri.activityInfo = ai;
1532 list.add(ri);
1533 }
1534 return list;
1535 }
1536
1537 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001538 String pkgName = intent.getPackage();
1539 if (pkgName == null) {
1540 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1541 resolvedType, flags);
1542 }
1543 PackageParser.Package pkg = mPackages.get(pkgName);
1544 if (pkg != null) {
1545 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1546 resolvedType, flags, pkg.activities);
1547 }
1548 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
1550 }
1551
1552 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1553 Intent[] specifics, String[] specificTypes, Intent intent,
1554 String resolvedType, int flags) {
1555 final String resultsAction = intent.getAction();
1556
1557 List<ResolveInfo> results = queryIntentActivities(
1558 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1559 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1560
1561 int specificsPos = 0;
1562 int N;
1563
1564 // todo: note that the algorithm used here is O(N^2). This
1565 // isn't a problem in our current environment, but if we start running
1566 // into situations where we have more than 5 or 10 matches then this
1567 // should probably be changed to something smarter...
1568
1569 // First we go through and resolve each of the specific items
1570 // that were supplied, taking care of removing any corresponding
1571 // duplicate items in the generic resolve list.
1572 if (specifics != null) {
1573 for (int i=0; i<specifics.length; i++) {
1574 final Intent sintent = specifics[i];
1575 if (sintent == null) {
1576 continue;
1577 }
1578
1579 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1580 String action = sintent.getAction();
1581 if (resultsAction != null && resultsAction.equals(action)) {
1582 // If this action was explicitly requested, then don't
1583 // remove things that have it.
1584 action = null;
1585 }
1586 ComponentName comp = sintent.getComponent();
1587 ResolveInfo ri = null;
1588 ActivityInfo ai = null;
1589 if (comp == null) {
1590 ri = resolveIntent(
1591 sintent,
1592 specificTypes != null ? specificTypes[i] : null,
1593 flags);
1594 if (ri == null) {
1595 continue;
1596 }
1597 if (ri == mResolveInfo) {
1598 // ACK! Must do something better with this.
1599 }
1600 ai = ri.activityInfo;
1601 comp = new ComponentName(ai.applicationInfo.packageName,
1602 ai.name);
1603 } else {
1604 ai = getActivityInfo(comp, flags);
1605 if (ai == null) {
1606 continue;
1607 }
1608 }
1609
1610 // Look for any generic query activities that are duplicates
1611 // of this specific one, and remove them from the results.
1612 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1613 N = results.size();
1614 int j;
1615 for (j=specificsPos; j<N; j++) {
1616 ResolveInfo sri = results.get(j);
1617 if ((sri.activityInfo.name.equals(comp.getClassName())
1618 && sri.activityInfo.applicationInfo.packageName.equals(
1619 comp.getPackageName()))
1620 || (action != null && sri.filter.matchAction(action))) {
1621 results.remove(j);
1622 if (Config.LOGV) Log.v(
1623 TAG, "Removing duplicate item from " + j
1624 + " due to specific " + specificsPos);
1625 if (ri == null) {
1626 ri = sri;
1627 }
1628 j--;
1629 N--;
1630 }
1631 }
1632
1633 // Add this specific item to its proper place.
1634 if (ri == null) {
1635 ri = new ResolveInfo();
1636 ri.activityInfo = ai;
1637 }
1638 results.add(specificsPos, ri);
1639 ri.specificIndex = i;
1640 specificsPos++;
1641 }
1642 }
1643
1644 // Now we go through the remaining generic results and remove any
1645 // duplicate actions that are found here.
1646 N = results.size();
1647 for (int i=specificsPos; i<N-1; i++) {
1648 final ResolveInfo rii = results.get(i);
1649 if (rii.filter == null) {
1650 continue;
1651 }
1652
1653 // Iterate over all of the actions of this result's intent
1654 // filter... typically this should be just one.
1655 final Iterator<String> it = rii.filter.actionsIterator();
1656 if (it == null) {
1657 continue;
1658 }
1659 while (it.hasNext()) {
1660 final String action = it.next();
1661 if (resultsAction != null && resultsAction.equals(action)) {
1662 // If this action was explicitly requested, then don't
1663 // remove things that have it.
1664 continue;
1665 }
1666 for (int j=i+1; j<N; j++) {
1667 final ResolveInfo rij = results.get(j);
1668 if (rij.filter != null && rij.filter.hasAction(action)) {
1669 results.remove(j);
1670 if (Config.LOGV) Log.v(
1671 TAG, "Removing duplicate item from " + j
1672 + " due to action " + action + " at " + i);
1673 j--;
1674 N--;
1675 }
1676 }
1677 }
1678
1679 // If the caller didn't request filter information, drop it now
1680 // so we don't have to marshall/unmarshall it.
1681 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1682 rii.filter = null;
1683 }
1684 }
1685
1686 // Filter out the caller activity if so requested.
1687 if (caller != null) {
1688 N = results.size();
1689 for (int i=0; i<N; i++) {
1690 ActivityInfo ainfo = results.get(i).activityInfo;
1691 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1692 && caller.getClassName().equals(ainfo.name)) {
1693 results.remove(i);
1694 break;
1695 }
1696 }
1697 }
1698
1699 // If the caller didn't request filter information,
1700 // drop them now so we don't have to
1701 // marshall/unmarshall it.
1702 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1703 N = results.size();
1704 for (int i=0; i<N; i++) {
1705 results.get(i).filter = null;
1706 }
1707 }
1708
1709 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1710 return results;
1711 }
1712
1713 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1714 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001715 ComponentName comp = intent.getComponent();
1716 if (comp != null) {
1717 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1718 ActivityInfo ai = getReceiverInfo(comp, flags);
1719 if (ai != null) {
1720 ResolveInfo ri = new ResolveInfo();
1721 ri.activityInfo = ai;
1722 list.add(ri);
1723 }
1724 return list;
1725 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001728 String pkgName = intent.getPackage();
1729 if (pkgName == null) {
1730 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1731 resolvedType, flags);
1732 }
1733 PackageParser.Package pkg = mPackages.get(pkgName);
1734 if (pkg != null) {
1735 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1736 resolvedType, flags, pkg.receivers);
1737 }
1738 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 }
1740 }
1741
1742 public ResolveInfo resolveService(Intent intent, String resolvedType,
1743 int flags) {
1744 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1745 flags);
1746 if (query != null) {
1747 if (query.size() >= 1) {
1748 // If there is more than one service with the same priority,
1749 // just arbitrarily pick the first one.
1750 return query.get(0);
1751 }
1752 }
1753 return null;
1754 }
1755
1756 public List<ResolveInfo> queryIntentServices(Intent intent,
1757 String resolvedType, int flags) {
1758 ComponentName comp = intent.getComponent();
1759 if (comp != null) {
1760 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1761 ServiceInfo si = getServiceInfo(comp, flags);
1762 if (si != null) {
1763 ResolveInfo ri = new ResolveInfo();
1764 ri.serviceInfo = si;
1765 list.add(ri);
1766 }
1767 return list;
1768 }
1769
1770 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001771 String pkgName = intent.getPackage();
1772 if (pkgName == null) {
1773 return (List<ResolveInfo>)mServices.queryIntent(intent,
1774 resolvedType, flags);
1775 }
1776 PackageParser.Package pkg = mPackages.get(pkgName);
1777 if (pkg != null) {
1778 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1779 resolvedType, flags, pkg.services);
1780 }
1781 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
1783 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 public List<PackageInfo> getInstalledPackages(int flags) {
1786 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1787
1788 synchronized (mPackages) {
1789 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1790 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1791 while (i.hasNext()) {
1792 final PackageSetting ps = i.next();
1793 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1794 if(psPkg != null) {
1795 finalList.add(psPkg);
1796 }
1797 }
1798 }
1799 else {
1800 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1801 while (i.hasNext()) {
1802 final PackageParser.Package p = i.next();
1803 if (p.applicationInfo != null) {
1804 PackageInfo pi = generatePackageInfo(p, flags);
1805 if(pi != null) {
1806 finalList.add(pi);
1807 }
1808 }
1809 }
1810 }
1811 }
1812 return finalList;
1813 }
1814
1815 public List<ApplicationInfo> getInstalledApplications(int flags) {
1816 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1817 synchronized(mPackages) {
1818 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1819 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1820 while (i.hasNext()) {
1821 final PackageSetting ps = i.next();
1822 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1823 if(ai != null) {
1824 finalList.add(ai);
1825 }
1826 }
1827 }
1828 else {
1829 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1830 while (i.hasNext()) {
1831 final PackageParser.Package p = i.next();
1832 if (p.applicationInfo != null) {
1833 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1834 if(ai != null) {
1835 finalList.add(ai);
1836 }
1837 }
1838 }
1839 }
1840 }
1841 return finalList;
1842 }
1843
1844 public List<ApplicationInfo> getPersistentApplications(int flags) {
1845 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1846
1847 synchronized (mPackages) {
1848 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1849 while (i.hasNext()) {
1850 PackageParser.Package p = i.next();
1851 if (p.applicationInfo != null
1852 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1853 && (!mSafeMode || (p.applicationInfo.flags
1854 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1855 finalList.add(p.applicationInfo);
1856 }
1857 }
1858 }
1859
1860 return finalList;
1861 }
1862
1863 public ProviderInfo resolveContentProvider(String name, int flags) {
1864 synchronized (mPackages) {
1865 final PackageParser.Provider provider = mProviders.get(name);
1866 return provider != null
1867 && mSettings.isEnabledLP(provider.info, flags)
1868 && (!mSafeMode || (provider.info.applicationInfo.flags
1869 &ApplicationInfo.FLAG_SYSTEM) != 0)
1870 ? PackageParser.generateProviderInfo(provider, flags)
1871 : null;
1872 }
1873 }
1874
Fred Quintana718d8a22009-04-29 17:53:20 -07001875 /**
1876 * @deprecated
1877 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 public void querySyncProviders(List outNames, List outInfo) {
1879 synchronized (mPackages) {
1880 Iterator<Map.Entry<String, PackageParser.Provider>> i
1881 = mProviders.entrySet().iterator();
1882
1883 while (i.hasNext()) {
1884 Map.Entry<String, PackageParser.Provider> entry = i.next();
1885 PackageParser.Provider p = entry.getValue();
1886
1887 if (p.syncable
1888 && (!mSafeMode || (p.info.applicationInfo.flags
1889 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1890 outNames.add(entry.getKey());
1891 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1892 }
1893 }
1894 }
1895 }
1896
1897 public List<ProviderInfo> queryContentProviders(String processName,
1898 int uid, int flags) {
1899 ArrayList<ProviderInfo> finalList = null;
1900
1901 synchronized (mPackages) {
1902 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1903 while (i.hasNext()) {
1904 PackageParser.Provider p = i.next();
1905 if (p.info.authority != null
1906 && (processName == null ||
1907 (p.info.processName.equals(processName)
1908 && p.info.applicationInfo.uid == uid))
1909 && mSettings.isEnabledLP(p.info, flags)
1910 && (!mSafeMode || (p.info.applicationInfo.flags
1911 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1912 if (finalList == null) {
1913 finalList = new ArrayList<ProviderInfo>(3);
1914 }
1915 finalList.add(PackageParser.generateProviderInfo(p,
1916 flags));
1917 }
1918 }
1919 }
1920
1921 if (finalList != null) {
1922 Collections.sort(finalList, mProviderInitOrderSorter);
1923 }
1924
1925 return finalList;
1926 }
1927
1928 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1929 int flags) {
1930 synchronized (mPackages) {
1931 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1932 return PackageParser.generateInstrumentationInfo(i, flags);
1933 }
1934 }
1935
1936 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1937 int flags) {
1938 ArrayList<InstrumentationInfo> finalList =
1939 new ArrayList<InstrumentationInfo>();
1940
1941 synchronized (mPackages) {
1942 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1943 while (i.hasNext()) {
1944 PackageParser.Instrumentation p = i.next();
1945 if (targetPackage == null
1946 || targetPackage.equals(p.info.targetPackage)) {
1947 finalList.add(PackageParser.generateInstrumentationInfo(p,
1948 flags));
1949 }
1950 }
1951 }
1952
1953 return finalList;
1954 }
1955
1956 private void scanDirLI(File dir, int flags, int scanMode) {
1957 Log.d(TAG, "Scanning app dir " + dir);
1958
1959 String[] files = dir.list();
1960
1961 int i;
1962 for (i=0; i<files.length; i++) {
1963 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001964 File resFile = file;
1965 // Pick up the resource path from settings for fwd locked apps
1966 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1967 resFile = null;
1968 }
1969 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1971 }
1972 }
1973
1974 private static void reportSettingsProblem(int priority, String msg) {
1975 try {
1976 File dataDir = Environment.getDataDirectory();
1977 File systemDir = new File(dataDir, "system");
1978 File fname = new File(systemDir, "uiderrors.txt");
1979 FileOutputStream out = new FileOutputStream(fname, true);
1980 PrintWriter pw = new PrintWriter(out);
1981 pw.println(msg);
1982 pw.close();
1983 FileUtils.setPermissions(
1984 fname.toString(),
1985 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1986 -1, -1);
1987 } catch (java.io.IOException e) {
1988 }
1989 Log.println(priority, TAG, msg);
1990 }
1991
1992 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1993 PackageParser.Package pkg, File srcFile, int parseFlags) {
1994 if (GET_CERTIFICATES) {
1995 if (ps == null || !ps.codePath.equals(srcFile)
1996 || ps.getTimeStamp() != srcFile.lastModified()) {
1997 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1998 if (!pp.collectCertificates(pkg, parseFlags)) {
1999 mLastScanError = pp.getParseError();
2000 return false;
2001 }
2002 }
2003 }
2004 return true;
2005 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 /*
2008 * Scan a package and return the newly parsed package.
2009 * Returns null in case of errors and the error code is stored in mLastScanError
2010 */
2011 private PackageParser.Package scanPackageLI(File scanFile,
2012 File destCodeFile, File destResourceFile, int parseFlags,
2013 int scanMode) {
2014 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2015 parseFlags |= mDefParseFlags;
2016 PackageParser pp = new PackageParser(scanFile.getPath());
2017 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2019 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2020 if (pkg == null) {
2021 mLastScanError = pp.getParseError();
2022 return null;
2023 }
2024 PackageSetting ps;
2025 PackageSetting updatedPkg;
2026 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002027 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2029 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002030 // Verify certificates first
2031 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2032 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2033 return null;
2034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 if (updatedPkg != null) {
2036 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2037 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2038 }
2039 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2040 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002041 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2042 if (pkg.mVersionCode < ps.versionCode) {
2043 // The system package has been updated and the code path does not match
2044 // Ignore entry. Just return
2045 Log.w(TAG, "Package:" + pkg.packageName +
2046 " has been updated. Ignoring the one from path:"+scanFile);
2047 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2048 return null;
2049 } else {
2050 // Delete the older apk pointed to by ps
2051 // At this point, its safely assumed that package installation for
2052 // apps in system partition will go through. If not there won't be a working
2053 // version of the app
2054 synchronized (mPackages) {
2055 // Just remove the loaded entries from package lists.
2056 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002057 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002058 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2059 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 }
2062 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 // The apk is forward locked (not public) if its code and resources
2064 // are kept in different files.
2065 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2066 scanMode |= SCAN_FORWARD_LOCKED;
2067 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002068 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002069 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002070 resFile = getFwdLockedResource(ps.name);
2071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002073 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2075 }
2076
2077 private static String fixProcessName(String defProcessName,
2078 String processName, int uid) {
2079 if (processName == null) {
2080 return defProcessName;
2081 }
2082 return processName;
2083 }
2084
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002085 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2087 if (pkg.mSignatures != null) {
2088 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2089 updateSignature)) {
2090 Log.e(TAG, "Package " + pkg.packageName
2091 + " signatures do not match the previously installed version; ignoring!");
2092 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2093 return false;
2094 }
2095
2096 if (pkgSetting.sharedUser != null) {
2097 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2098 pkg.mSignatures, updateSignature)) {
2099 Log.e(TAG, "Package " + pkg.packageName
2100 + " has no signatures that match those in shared user "
2101 + pkgSetting.sharedUser.name + "; ignoring!");
2102 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2103 return false;
2104 }
2105 }
2106 } else {
2107 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2108 }
2109 return true;
2110 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002111
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002112 public boolean performDexOpt(String packageName) {
2113 if (!mNoDexOpt) {
2114 return false;
2115 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002116
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002117 PackageParser.Package p;
2118 synchronized (mPackages) {
2119 p = mPackages.get(packageName);
2120 if (p == null || p.mDidDexOpt) {
2121 return false;
2122 }
2123 }
2124 synchronized (mInstallLock) {
2125 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2126 }
2127 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002128
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002129 static final int DEX_OPT_SKIPPED = 0;
2130 static final int DEX_OPT_PERFORMED = 1;
2131 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002132
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002133 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2134 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002135 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002136 String path = pkg.mScanPath;
2137 int ret = 0;
2138 try {
2139 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002140 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002141 !pkg.mForwardLocked);
2142 pkg.mDidDexOpt = true;
2143 performed = true;
2144 }
2145 } catch (FileNotFoundException e) {
2146 Log.w(TAG, "Apk not found for dexopt: " + path);
2147 ret = -1;
2148 } catch (IOException e) {
2149 Log.w(TAG, "Exception reading apk: " + path, e);
2150 ret = -1;
2151 }
2152 if (ret < 0) {
2153 //error from installer
2154 return DEX_OPT_FAILED;
2155 }
2156 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002157
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002158 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2159 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002160
2161 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2162 return Environment.isEncryptedFilesystemEnabled() &&
2163 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2164 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 private PackageParser.Package scanPackageLI(
2167 File scanFile, File destCodeFile, File destResourceFile,
2168 PackageParser.Package pkg, int parseFlags, int scanMode) {
2169
2170 mScanningPath = scanFile;
2171 if (pkg == null) {
2172 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2173 return null;
2174 }
2175
2176 final String pkgName = pkg.applicationInfo.packageName;
2177 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2178 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2179 }
2180
2181 if (pkgName.equals("android")) {
2182 synchronized (mPackages) {
2183 if (mAndroidApplication != null) {
2184 Log.w(TAG, "*************************************************");
2185 Log.w(TAG, "Core android package being redefined. Skipping.");
2186 Log.w(TAG, " file=" + mScanningPath);
2187 Log.w(TAG, "*************************************************");
2188 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2189 return null;
2190 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 // Set up information for our fall-back user intent resolution
2193 // activity.
2194 mPlatformPackage = pkg;
2195 pkg.mVersionCode = mSdkVersion;
2196 mAndroidApplication = pkg.applicationInfo;
2197 mResolveActivity.applicationInfo = mAndroidApplication;
2198 mResolveActivity.name = ResolverActivity.class.getName();
2199 mResolveActivity.packageName = mAndroidApplication.packageName;
2200 mResolveActivity.processName = mAndroidApplication.processName;
2201 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2202 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2203 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2204 mResolveActivity.exported = true;
2205 mResolveActivity.enabled = true;
2206 mResolveInfo.activityInfo = mResolveActivity;
2207 mResolveInfo.priority = 0;
2208 mResolveInfo.preferredOrder = 0;
2209 mResolveInfo.match = 0;
2210 mResolveComponentName = new ComponentName(
2211 mAndroidApplication.packageName, mResolveActivity.name);
2212 }
2213 }
2214
2215 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2216 TAG, "Scanning package " + pkgName);
2217 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2218 Log.w(TAG, "*************************************************");
2219 Log.w(TAG, "Application package " + pkgName
2220 + " already installed. Skipping duplicate.");
2221 Log.w(TAG, "*************************************************");
2222 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2223 return null;
2224 }
2225
2226 SharedUserSetting suid = null;
2227 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 synchronized (mPackages) {
2232 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002233 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2234 if (mTmpSharedLibraries == null ||
2235 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2236 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2237 }
2238 int num = 0;
2239 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2240 for (int i=0; i<N; i++) {
2241 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 if (file == null) {
2243 Log.e(TAG, "Package " + pkg.packageName
2244 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002245 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2247 return null;
2248 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002249 mTmpSharedLibraries[num] = file;
2250 num++;
2251 }
2252 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2253 for (int i=0; i<N; i++) {
2254 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2255 if (file == null) {
2256 Log.w(TAG, "Package " + pkg.packageName
2257 + " desires unavailable shared library "
2258 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2259 } else {
2260 mTmpSharedLibraries[num] = file;
2261 num++;
2262 }
2263 }
2264 if (num > 0) {
2265 pkg.usesLibraryFiles = new String[num];
2266 System.arraycopy(mTmpSharedLibraries, 0,
2267 pkg.usesLibraryFiles, 0, num);
2268 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002269
Dianne Hackborn49237342009-08-27 20:08:01 -07002270 if (pkg.reqFeatures != null) {
2271 N = pkg.reqFeatures.size();
2272 for (int i=0; i<N; i++) {
2273 FeatureInfo fi = pkg.reqFeatures.get(i);
2274 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2275 // Don't care.
2276 continue;
2277 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002278
Dianne Hackborn49237342009-08-27 20:08:01 -07002279 if (fi.name != null) {
2280 if (mAvailableFeatures.get(fi.name) == null) {
2281 Log.e(TAG, "Package " + pkg.packageName
2282 + " requires unavailable feature "
2283 + fi.name + "; failing!");
2284 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2285 return null;
2286 }
2287 }
2288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 }
2290 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 if (pkg.mSharedUserId != null) {
2293 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2294 pkg.applicationInfo.flags, true);
2295 if (suid == null) {
2296 Log.w(TAG, "Creating application package " + pkgName
2297 + " for shared user failed");
2298 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2299 return null;
2300 }
2301 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2302 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2303 + suid.userId + "): packages=" + suid.packages);
2304 }
2305 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002306
2307 // Just create the setting, don't add it yet. For already existing packages
2308 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2310 destResourceFile, pkg.applicationInfo.flags, true, false);
2311 if (pkgSetting == null) {
2312 Log.w(TAG, "Creating application package " + pkgName + " failed");
2313 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2314 return null;
2315 }
2316 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2317 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2318 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 pkg.applicationInfo.uid = pkgSetting.userId;
2321 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002322
2323 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2325 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2326 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2327 return null;
2328 }
2329 // The signature has changed, but this package is in the system
2330 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002331 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 // However... if this package is part of a shared user, but it
2333 // doesn't match the signature of the shared user, let's fail.
2334 // What this means is that you can't change the signatures
2335 // associated with an overall shared user, which doesn't seem all
2336 // that unreasonable.
2337 if (pkgSetting.sharedUser != null) {
2338 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2339 pkg.mSignatures, false)) {
2340 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2341 return null;
2342 }
2343 }
2344 removeExisting = true;
2345 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002346
The Android Open Source Project10592532009-03-18 17:39:46 -07002347 // Verify that this new package doesn't have any content providers
2348 // that conflict with existing packages. Only do this if the
2349 // package isn't already installed, since we don't want to break
2350 // things that are installed.
2351 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2352 int N = pkg.providers.size();
2353 int i;
2354 for (i=0; i<N; i++) {
2355 PackageParser.Provider p = pkg.providers.get(i);
2356 String names[] = p.info.authority.split(";");
2357 for (int j = 0; j < names.length; j++) {
2358 if (mProviders.containsKey(names[j])) {
2359 PackageParser.Provider other = mProviders.get(names[j]);
2360 Log.w(TAG, "Can't install because provider name " + names[j] +
2361 " (in package " + pkg.applicationInfo.packageName +
2362 ") is already used by "
2363 + ((other != null && other.component != null)
2364 ? other.component.getPackageName() : "?"));
2365 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2366 return null;
2367 }
2368 }
2369 }
2370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 }
2372
2373 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002374 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002376 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002377 if (ret != 0) {
2378 String msg = "System package " + pkg.packageName
2379 + " could not have data directory erased after signature change.";
2380 reportSettingsProblem(Log.WARN, msg);
2381 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2382 return null;
2383 }
2384 }
2385 Log.w(TAG, "System package " + pkg.packageName
2386 + " signature changed: existing data removed.");
2387 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002390 long scanFileTime = scanFile.lastModified();
2391 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2392 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2393 pkg.applicationInfo.processName = fixProcessName(
2394 pkg.applicationInfo.packageName,
2395 pkg.applicationInfo.processName,
2396 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002397 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398
2399 File dataPath;
2400 if (mPlatformPackage == pkg) {
2401 // The system package is special.
2402 dataPath = new File (Environment.getDataDirectory(), "system");
2403 pkg.applicationInfo.dataDir = dataPath.getPath();
2404 } else {
2405 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002406 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2407 if (useEncryptedFSDir) {
2408 dataPath = new File(mSecureAppDataDir, pkgName);
2409 } else {
2410 dataPath = new File(mAppDataDir, pkgName);
2411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 if (dataPath.exists()) {
2413 mOutPermissions[1] = 0;
2414 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2415 if (mOutPermissions[1] == pkg.applicationInfo.uid
2416 || !Process.supportsProcesses()) {
2417 pkg.applicationInfo.dataDir = dataPath.getPath();
2418 } else {
2419 boolean recovered = false;
2420 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2421 // If this is a system app, we can at least delete its
2422 // current data so the application will still work.
2423 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002424 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 if(ret >= 0) {
2426 // Old data gone!
2427 String msg = "System package " + pkg.packageName
2428 + " has changed from uid: "
2429 + mOutPermissions[1] + " to "
2430 + pkg.applicationInfo.uid + "; old data erased";
2431 reportSettingsProblem(Log.WARN, msg);
2432 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002435 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 pkg.applicationInfo.uid);
2437 if (ret == -1) {
2438 // Ack should not happen!
2439 msg = "System package " + pkg.packageName
2440 + " could not have data directory re-created after delete.";
2441 reportSettingsProblem(Log.WARN, msg);
2442 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2443 return null;
2444 }
2445 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 if (!recovered) {
2448 mHasSystemUidErrors = true;
2449 }
2450 }
2451 if (!recovered) {
2452 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2453 + pkg.applicationInfo.uid + "/fs_"
2454 + mOutPermissions[1];
2455 String msg = "Package " + pkg.packageName
2456 + " has mismatched uid: "
2457 + mOutPermissions[1] + " on disk, "
2458 + pkg.applicationInfo.uid + " in settings";
2459 synchronized (mPackages) {
2460 if (!mReportedUidError) {
2461 mReportedUidError = true;
2462 msg = msg + "; read messages:\n"
2463 + mSettings.getReadMessagesLP();
2464 }
2465 reportSettingsProblem(Log.ERROR, msg);
2466 }
2467 }
2468 }
2469 pkg.applicationInfo.dataDir = dataPath.getPath();
2470 } else {
2471 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2472 Log.v(TAG, "Want this data dir: " + dataPath);
2473 //invoke installer to do the actual installation
2474 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002475 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 pkg.applicationInfo.uid);
2477 if(ret < 0) {
2478 // Error from installer
2479 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2480 return null;
2481 }
2482 } else {
2483 dataPath.mkdirs();
2484 if (dataPath.exists()) {
2485 FileUtils.setPermissions(
2486 dataPath.toString(),
2487 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2488 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2489 }
2490 }
2491 if (dataPath.exists()) {
2492 pkg.applicationInfo.dataDir = dataPath.getPath();
2493 } else {
2494 Log.w(TAG, "Unable to create data directory: " + dataPath);
2495 pkg.applicationInfo.dataDir = null;
2496 }
2497 }
2498 }
2499
2500 // Perform shared library installation and dex validation and
2501 // optimization, if this is not a system app.
2502 if (mInstaller != null) {
2503 String path = scanFile.getPath();
2504 if (scanFileNewer) {
2505 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002506 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2507 if (err != PackageManager.INSTALL_SUCCEEDED) {
2508 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 return null;
2510 }
2511 }
2512
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002513 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2514 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002515
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002516 if ((scanMode&SCAN_NO_DEX) == 0) {
2517 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2519 return null;
2520 }
2521 }
2522 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 if (mFactoryTest && pkg.requestedPermissions.contains(
2525 android.Manifest.permission.FACTORY_TEST)) {
2526 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2527 }
2528
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002529 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 if ((scanMode&SCAN_MONITOR) != 0) {
2531 pkg.mPath = destCodeFile.getAbsolutePath();
2532 mAppDirs.put(pkg.mPath, pkg);
2533 }
2534
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002535 // Request the ActivityManager to kill the process(only for existing packages)
2536 // so that we do not end up in a confused state while the user is still using the older
2537 // version of the application while the new one gets installed.
2538 IActivityManager am = ActivityManagerNative.getDefault();
2539 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2540 try {
2541 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2542 pkg.applicationInfo.uid);
2543 } catch (RemoteException e) {
2544 }
2545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002548 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002550 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 int N = pkg.providers.size();
2552 StringBuilder r = null;
2553 int i;
2554 for (i=0; i<N; i++) {
2555 PackageParser.Provider p = pkg.providers.get(i);
2556 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2557 p.info.processName, pkg.applicationInfo.uid);
2558 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2559 p.info.name), p);
2560 p.syncable = p.info.isSyncable;
2561 String names[] = p.info.authority.split(";");
2562 p.info.authority = null;
2563 for (int j = 0; j < names.length; j++) {
2564 if (j == 1 && p.syncable) {
2565 // We only want the first authority for a provider to possibly be
2566 // syncable, so if we already added this provider using a different
2567 // authority clear the syncable flag. We copy the provider before
2568 // changing it because the mProviders object contains a reference
2569 // to a provider that we don't want to change.
2570 // Only do this for the second authority since the resulting provider
2571 // object can be the same for all future authorities for this provider.
2572 p = new PackageParser.Provider(p);
2573 p.syncable = false;
2574 }
2575 if (!mProviders.containsKey(names[j])) {
2576 mProviders.put(names[j], p);
2577 if (p.info.authority == null) {
2578 p.info.authority = names[j];
2579 } else {
2580 p.info.authority = p.info.authority + ";" + names[j];
2581 }
2582 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2583 Log.d(TAG, "Registered content provider: " + names[j] +
2584 ", className = " + p.info.name +
2585 ", isSyncable = " + p.info.isSyncable);
2586 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002587 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 Log.w(TAG, "Skipping provider name " + names[j] +
2589 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002590 "): name already used by "
2591 + ((other != null && other.component != null)
2592 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594 }
2595 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2596 if (r == null) {
2597 r = new StringBuilder(256);
2598 } else {
2599 r.append(' ');
2600 }
2601 r.append(p.info.name);
2602 }
2603 }
2604 if (r != null) {
2605 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608 N = pkg.services.size();
2609 r = null;
2610 for (i=0; i<N; i++) {
2611 PackageParser.Service s = pkg.services.get(i);
2612 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2613 s.info.processName, pkg.applicationInfo.uid);
2614 mServices.addService(s);
2615 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2616 if (r == null) {
2617 r = new StringBuilder(256);
2618 } else {
2619 r.append(' ');
2620 }
2621 r.append(s.info.name);
2622 }
2623 }
2624 if (r != null) {
2625 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2626 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002628 N = pkg.receivers.size();
2629 r = null;
2630 for (i=0; i<N; i++) {
2631 PackageParser.Activity a = pkg.receivers.get(i);
2632 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2633 a.info.processName, pkg.applicationInfo.uid);
2634 mReceivers.addActivity(a, "receiver");
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(a.info.name);
2642 }
2643 }
2644 if (r != null) {
2645 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2646 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002648 N = pkg.activities.size();
2649 r = null;
2650 for (i=0; i<N; i++) {
2651 PackageParser.Activity a = pkg.activities.get(i);
2652 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2653 a.info.processName, pkg.applicationInfo.uid);
2654 mActivities.addActivity(a, "activity");
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(a.info.name);
2662 }
2663 }
2664 if (r != null) {
2665 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2666 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 N = pkg.permissionGroups.size();
2669 r = null;
2670 for (i=0; i<N; i++) {
2671 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2672 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2673 if (cur == null) {
2674 mPermissionGroups.put(pg.info.name, pg);
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(pg.info.name);
2682 }
2683 } else {
2684 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2685 + pg.info.packageName + " ignored: original from "
2686 + cur.info.packageName);
2687 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2688 if (r == null) {
2689 r = new StringBuilder(256);
2690 } else {
2691 r.append(' ');
2692 }
2693 r.append("DUP:");
2694 r.append(pg.info.name);
2695 }
2696 }
2697 }
2698 if (r != null) {
2699 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2700 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 N = pkg.permissions.size();
2703 r = null;
2704 for (i=0; i<N; i++) {
2705 PackageParser.Permission p = pkg.permissions.get(i);
2706 HashMap<String, BasePermission> permissionMap =
2707 p.tree ? mSettings.mPermissionTrees
2708 : mSettings.mPermissions;
2709 p.group = mPermissionGroups.get(p.info.group);
2710 if (p.info.group == null || p.group != null) {
2711 BasePermission bp = permissionMap.get(p.info.name);
2712 if (bp == null) {
2713 bp = new BasePermission(p.info.name, p.info.packageName,
2714 BasePermission.TYPE_NORMAL);
2715 permissionMap.put(p.info.name, bp);
2716 }
2717 if (bp.perm == null) {
2718 if (bp.sourcePackage == null
2719 || bp.sourcePackage.equals(p.info.packageName)) {
2720 BasePermission tree = findPermissionTreeLP(p.info.name);
2721 if (tree == null
2722 || tree.sourcePackage.equals(p.info.packageName)) {
2723 bp.perm = p;
2724 bp.uid = pkg.applicationInfo.uid;
2725 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2726 if (r == null) {
2727 r = new StringBuilder(256);
2728 } else {
2729 r.append(' ');
2730 }
2731 r.append(p.info.name);
2732 }
2733 } else {
2734 Log.w(TAG, "Permission " + p.info.name + " from package "
2735 + p.info.packageName + " ignored: base tree "
2736 + tree.name + " is from package "
2737 + tree.sourcePackage);
2738 }
2739 } else {
2740 Log.w(TAG, "Permission " + p.info.name + " from package "
2741 + p.info.packageName + " ignored: original from "
2742 + bp.sourcePackage);
2743 }
2744 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2745 if (r == null) {
2746 r = new StringBuilder(256);
2747 } else {
2748 r.append(' ');
2749 }
2750 r.append("DUP:");
2751 r.append(p.info.name);
2752 }
2753 } else {
2754 Log.w(TAG, "Permission " + p.info.name + " from package "
2755 + p.info.packageName + " ignored: no group "
2756 + p.group);
2757 }
2758 }
2759 if (r != null) {
2760 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 N = pkg.instrumentation.size();
2764 r = null;
2765 for (i=0; i<N; i++) {
2766 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2767 a.info.packageName = pkg.applicationInfo.packageName;
2768 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2769 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2770 a.info.dataDir = pkg.applicationInfo.dataDir;
2771 mInstrumentation.put(a.component, a);
2772 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2773 if (r == null) {
2774 r = new StringBuilder(256);
2775 } else {
2776 r.append(' ');
2777 }
2778 r.append(a.info.name);
2779 }
2780 }
2781 if (r != null) {
2782 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2783 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002784
Dianne Hackborn854060af2009-07-09 18:14:31 -07002785 if (pkg.protectedBroadcasts != null) {
2786 N = pkg.protectedBroadcasts.size();
2787 for (i=0; i<N; i++) {
2788 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2789 }
2790 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 pkgSetting.setTimeStamp(scanFileTime);
2793 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 return pkg;
2796 }
2797
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002798 // The following constants are returned by cachePackageSharedLibsForAbiLI
2799 // to indicate if native shared libraries were found in the package.
2800 // Values are:
2801 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2802 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2803 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2804 // in package (and not installed)
2805 //
2806 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2807 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2808 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002809
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002810 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2811 // and automatically copy them to /data/data/<appname>/lib if present.
2812 //
2813 // NOTE: this method may throw an IOException if the library cannot
2814 // be copied to its final destination, e.g. if there isn't enough
2815 // room left on the data partition, or a ZipException if the package
2816 // file is malformed.
2817 //
2818 private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg,
2819 File dataPath, File scanFile, String cpuAbi)
2820 throws IOException, ZipException {
2821 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2822 final String apkLib = "lib/";
2823 final int apkLibLen = apkLib.length();
2824 final int cpuAbiLen = cpuAbi.length();
2825 final String libPrefix = "lib";
2826 final int libPrefixLen = libPrefix.length();
2827 final String libSuffix = ".so";
2828 final int libSuffixLen = libSuffix.length();
2829 boolean hasNativeLibraries = false;
2830 boolean installedNativeLibraries = false;
2831
2832 // the minimum length of a valid native shared library of the form
2833 // lib/<something>/lib<name>.so.
2834 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2835
2836 ZipFile zipFile = new ZipFile(scanFile);
2837 Enumeration<ZipEntry> entries =
2838 (Enumeration<ZipEntry>) zipFile.entries();
2839
2840 while (entries.hasMoreElements()) {
2841 ZipEntry entry = entries.nextElement();
2842 // skip directories
2843 if (entry.isDirectory()) {
2844 continue;
2845 }
2846 String entryName = entry.getName();
2847
2848 // check that the entry looks like lib/<something>/lib<name>.so
2849 // here, but don't check the ABI just yet.
2850 //
2851 // - must be sufficiently long
2852 // - must end with libSuffix, i.e. ".so"
2853 // - must start with apkLib, i.e. "lib/"
2854 if (entryName.length() < minEntryLen ||
2855 !entryName.endsWith(libSuffix) ||
2856 !entryName.startsWith(apkLib) ) {
2857 continue;
2858 }
2859
2860 // file name must start with libPrefix, i.e. "lib"
2861 int lastSlash = entryName.lastIndexOf('/');
2862
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002863 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002864 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2865 continue;
2866 }
2867
2868 hasNativeLibraries = true;
2869
2870 // check the cpuAbi now, between lib/ and /lib<name>.so
2871 //
2872 if (lastSlash != apkLibLen + cpuAbiLen ||
2873 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2874 continue;
2875
2876 // extract the library file name, ensure it doesn't contain
2877 // weird characters. we're guaranteed here that it doesn't contain
2878 // a directory separator though.
2879 String libFileName = entryName.substring(lastSlash+1);
2880 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2881 continue;
2882 }
2883
2884 installedNativeLibraries = true;
2885
2886 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2887 File.separator + libFileName;
2888 File sharedLibraryFile = new File(sharedLibraryFilePath);
2889 if (! sharedLibraryFile.exists() ||
2890 sharedLibraryFile.length() != entry.getSize() ||
2891 sharedLibraryFile.lastModified() != entry.getTime()) {
2892 if (Config.LOGD) {
2893 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002895 if (mInstaller == null) {
2896 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002897 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002898 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2899 sharedLibraryFile);
2900 }
2901 }
2902 if (!hasNativeLibraries)
2903 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2904
2905 if (!installedNativeLibraries)
2906 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
2907
2908 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2909 }
2910
2911 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
2912 // and copy them to /data/data/<appname>/lib.
2913 //
2914 // This function will first try the main CPU ABI defined by Build.CPU_ABI
2915 // (which corresponds to ro.product.cpu.abi), and also try an alternate
2916 // one if ro.product.cpu.abi2 is defined.
2917 //
2918 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2919 File dataPath, File scanFile) {
2920 final String cpuAbi = Build.CPU_ABI;
2921 try {
2922 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
2923
2924 // some architectures are capable of supporting several CPU ABIs
2925 // for example, 'armeabi-v7a' also supports 'armeabi' native code
2926 // this is indicated by the definition of the ro.product.cpu.abi2
2927 // system property.
2928 //
2929 // only scan the package twice in case of ABI mismatch
2930 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2931 String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
2932 if (cpuAbi2 != null) {
2933 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002935
2936 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2937 Log.w(TAG,"Native ABI mismatch from package file");
2938 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
2940 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002941 } catch (ZipException e) {
2942 Log.w(TAG, "Failed to extract data from package file", e);
2943 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002945 Log.w(TAG, "Failed to cache package shared libs", e);
2946 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002948 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 }
2950
2951 private void cacheSharedLibLI(PackageParser.Package pkg,
2952 ZipFile zipFile, ZipEntry entry,
2953 File sharedLibraryDir,
2954 File sharedLibraryFile) throws IOException {
2955 InputStream inputStream = zipFile.getInputStream(entry);
2956 try {
2957 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2958 String tempFilePath = tempFile.getPath();
2959 // XXX package manager can't change owner, so the lib files for
2960 // now need to be left as world readable and owned by the system.
2961 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2962 ! tempFile.setLastModified(entry.getTime()) ||
2963 FileUtils.setPermissions(tempFilePath,
2964 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2965 |FileUtils.S_IROTH, -1, -1) != 0 ||
2966 ! tempFile.renameTo(sharedLibraryFile)) {
2967 // Failed to properly write file.
2968 tempFile.delete();
2969 throw new IOException("Couldn't create cached shared lib "
2970 + sharedLibraryFile + " in " + sharedLibraryDir);
2971 }
2972 } finally {
2973 inputStream.close();
2974 }
2975 }
2976
2977 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2978 if (chatty && Config.LOGD) Log.d(
2979 TAG, "Removing package " + pkg.applicationInfo.packageName );
2980
2981 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 mPackages.remove(pkg.applicationInfo.packageName);
2985 if (pkg.mPath != null) {
2986 mAppDirs.remove(pkg.mPath);
2987 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 PackageSetting ps = (PackageSetting)pkg.mExtras;
2990 if (ps != null && ps.sharedUser != null) {
2991 // XXX don't do this until the data is removed.
2992 if (false) {
2993 ps.sharedUser.packages.remove(ps);
2994 if (ps.sharedUser.packages.size() == 0) {
2995 // Remove.
2996 }
2997 }
2998 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 int N = pkg.providers.size();
3001 StringBuilder r = null;
3002 int i;
3003 for (i=0; i<N; i++) {
3004 PackageParser.Provider p = pkg.providers.get(i);
3005 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3006 p.info.name));
3007 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 /* The is another ContentProvider with this authority when
3010 * this app was installed so this authority is null,
3011 * Ignore it as we don't have to unregister the provider.
3012 */
3013 continue;
3014 }
3015 String names[] = p.info.authority.split(";");
3016 for (int j = 0; j < names.length; j++) {
3017 if (mProviders.get(names[j]) == p) {
3018 mProviders.remove(names[j]);
3019 if (chatty && Config.LOGD) Log.d(
3020 TAG, "Unregistered content provider: " + names[j] +
3021 ", className = " + p.info.name +
3022 ", isSyncable = " + p.info.isSyncable);
3023 }
3024 }
3025 if (chatty) {
3026 if (r == null) {
3027 r = new StringBuilder(256);
3028 } else {
3029 r.append(' ');
3030 }
3031 r.append(p.info.name);
3032 }
3033 }
3034 if (r != null) {
3035 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3036 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 N = pkg.services.size();
3039 r = null;
3040 for (i=0; i<N; i++) {
3041 PackageParser.Service s = pkg.services.get(i);
3042 mServices.removeService(s);
3043 if (chatty) {
3044 if (r == null) {
3045 r = new StringBuilder(256);
3046 } else {
3047 r.append(' ');
3048 }
3049 r.append(s.info.name);
3050 }
3051 }
3052 if (r != null) {
3053 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3054 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003056 N = pkg.receivers.size();
3057 r = null;
3058 for (i=0; i<N; i++) {
3059 PackageParser.Activity a = pkg.receivers.get(i);
3060 mReceivers.removeActivity(a, "receiver");
3061 if (chatty) {
3062 if (r == null) {
3063 r = new StringBuilder(256);
3064 } else {
3065 r.append(' ');
3066 }
3067 r.append(a.info.name);
3068 }
3069 }
3070 if (r != null) {
3071 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 N = pkg.activities.size();
3075 r = null;
3076 for (i=0; i<N; i++) {
3077 PackageParser.Activity a = pkg.activities.get(i);
3078 mActivities.removeActivity(a, "activity");
3079 if (chatty) {
3080 if (r == null) {
3081 r = new StringBuilder(256);
3082 } else {
3083 r.append(' ');
3084 }
3085 r.append(a.info.name);
3086 }
3087 }
3088 if (r != null) {
3089 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3090 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003092 N = pkg.permissions.size();
3093 r = null;
3094 for (i=0; i<N; i++) {
3095 PackageParser.Permission p = pkg.permissions.get(i);
3096 boolean tree = false;
3097 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3098 if (bp == null) {
3099 tree = true;
3100 bp = mSettings.mPermissionTrees.get(p.info.name);
3101 }
3102 if (bp != null && bp.perm == p) {
3103 if (bp.type != BasePermission.TYPE_BUILTIN) {
3104 if (tree) {
3105 mSettings.mPermissionTrees.remove(p.info.name);
3106 } else {
3107 mSettings.mPermissions.remove(p.info.name);
3108 }
3109 } else {
3110 bp.perm = null;
3111 }
3112 if (chatty) {
3113 if (r == null) {
3114 r = new StringBuilder(256);
3115 } else {
3116 r.append(' ');
3117 }
3118 r.append(p.info.name);
3119 }
3120 }
3121 }
3122 if (r != null) {
3123 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3124 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 N = pkg.instrumentation.size();
3127 r = null;
3128 for (i=0; i<N; i++) {
3129 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3130 mInstrumentation.remove(a.component);
3131 if (chatty) {
3132 if (r == null) {
3133 r = new StringBuilder(256);
3134 } else {
3135 r.append(' ');
3136 }
3137 r.append(a.info.name);
3138 }
3139 }
3140 if (r != null) {
3141 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3142 }
3143 }
3144 }
3145
3146 private static final boolean isPackageFilename(String name) {
3147 return name != null && name.endsWith(".apk");
3148 }
3149
3150 private void updatePermissionsLP() {
3151 // Make sure there are no dangling permission trees.
3152 Iterator<BasePermission> it = mSettings.mPermissionTrees
3153 .values().iterator();
3154 while (it.hasNext()) {
3155 BasePermission bp = it.next();
3156 if (bp.perm == null) {
3157 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3158 + " from package " + bp.sourcePackage);
3159 it.remove();
3160 }
3161 }
3162
3163 // Make sure all dynamic permissions have been assigned to a package,
3164 // and make sure there are no dangling permissions.
3165 it = mSettings.mPermissions.values().iterator();
3166 while (it.hasNext()) {
3167 BasePermission bp = it.next();
3168 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3169 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3170 + bp.name + " pkg=" + bp.sourcePackage
3171 + " info=" + bp.pendingInfo);
3172 if (bp.perm == null && bp.pendingInfo != null) {
3173 BasePermission tree = findPermissionTreeLP(bp.name);
3174 if (tree != null) {
3175 bp.perm = new PackageParser.Permission(tree.perm.owner,
3176 new PermissionInfo(bp.pendingInfo));
3177 bp.perm.info.packageName = tree.perm.info.packageName;
3178 bp.perm.info.name = bp.name;
3179 bp.uid = tree.uid;
3180 }
3181 }
3182 }
3183 if (bp.perm == null) {
3184 Log.w(TAG, "Removing dangling permission: " + bp.name
3185 + " from package " + bp.sourcePackage);
3186 it.remove();
3187 }
3188 }
3189
3190 // Now update the permissions for all packages, in particular
3191 // replace the granted permissions of the system packages.
3192 for (PackageParser.Package pkg : mPackages.values()) {
3193 grantPermissionsLP(pkg, false);
3194 }
3195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3198 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3199 if (ps == null) {
3200 return;
3201 }
3202 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3203 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 if (replace) {
3206 ps.permissionsFixed = false;
3207 if (gp == ps) {
3208 gp.grantedPermissions.clear();
3209 gp.gids = mGlobalGids;
3210 }
3211 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003213 if (gp.gids == null) {
3214 gp.gids = mGlobalGids;
3215 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003217 final int N = pkg.requestedPermissions.size();
3218 for (int i=0; i<N; i++) {
3219 String name = pkg.requestedPermissions.get(i);
3220 BasePermission bp = mSettings.mPermissions.get(name);
3221 PackageParser.Permission p = bp != null ? bp.perm : null;
3222 if (false) {
3223 if (gp != ps) {
3224 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3225 + ": " + p);
3226 }
3227 }
3228 if (p != null) {
3229 final String perm = p.info.name;
3230 boolean allowed;
3231 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3232 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3233 allowed = true;
3234 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3235 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003236 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003237 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003238 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 == PackageManager.SIGNATURE_MATCH);
3240 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3241 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3242 // For updated system applications, the signatureOrSystem permission
3243 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003244 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3246 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3247 if(sysPs.grantedPermissions.contains(perm)) {
3248 allowed = true;
3249 } else {
3250 allowed = false;
3251 }
3252 } else {
3253 allowed = true;
3254 }
3255 }
3256 }
3257 } else {
3258 allowed = false;
3259 }
3260 if (false) {
3261 if (gp != ps) {
3262 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3263 }
3264 }
3265 if (allowed) {
3266 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3267 && ps.permissionsFixed) {
3268 // If this is an existing, non-system package, then
3269 // we can't add any new permissions to it.
3270 if (!gp.loadedPermissions.contains(perm)) {
3271 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003272 // Except... if this is a permission that was added
3273 // to the platform (note: need to only do this when
3274 // updating the platform).
3275 final int NP = PackageParser.NEW_PERMISSIONS.length;
3276 for (int ip=0; ip<NP; ip++) {
3277 final PackageParser.NewPermissionInfo npi
3278 = PackageParser.NEW_PERMISSIONS[ip];
3279 if (npi.name.equals(perm)
3280 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3281 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003282 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003283 + pkg.packageName);
3284 break;
3285 }
3286 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 }
3288 }
3289 if (allowed) {
3290 if (!gp.grantedPermissions.contains(perm)) {
3291 addedPermission = true;
3292 gp.grantedPermissions.add(perm);
3293 gp.gids = appendInts(gp.gids, bp.gids);
3294 }
3295 } else {
3296 Log.w(TAG, "Not granting permission " + perm
3297 + " to package " + pkg.packageName
3298 + " because it was previously installed without");
3299 }
3300 } else {
3301 Log.w(TAG, "Not granting permission " + perm
3302 + " to package " + pkg.packageName
3303 + " (protectionLevel=" + p.info.protectionLevel
3304 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3305 + ")");
3306 }
3307 } else {
3308 Log.w(TAG, "Unknown permission " + name
3309 + " in package " + pkg.packageName);
3310 }
3311 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003314 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3315 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 // This is the first that we have heard about this package, so the
3317 // permissions we have now selected are fixed until explicitly
3318 // changed.
3319 ps.permissionsFixed = true;
3320 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3321 }
3322 }
3323
3324 private final class ActivityIntentResolver
3325 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003326 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003328 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 }
3330
Mihai Preda074edef2009-05-18 17:13:31 +02003331 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003332 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003333 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003334 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3335 }
3336
Mihai Predaeae850c2009-05-13 10:13:48 +02003337 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3338 ArrayList<PackageParser.Activity> packageActivities) {
3339 if (packageActivities == null) {
3340 return null;
3341 }
3342 mFlags = flags;
3343 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3344 int N = packageActivities.size();
3345 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3346 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003347
3348 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003349 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003350 intentFilters = packageActivities.get(i).intents;
3351 if (intentFilters != null && intentFilters.size() > 0) {
3352 listCut.add(intentFilters);
3353 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003354 }
3355 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3356 }
3357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 public final void addActivity(PackageParser.Activity a, String type) {
3359 mActivities.put(a.component, a);
3360 if (SHOW_INFO || Config.LOGV) Log.v(
3361 TAG, " " + type + " " +
3362 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3363 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3364 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003365 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3367 if (SHOW_INFO || Config.LOGV) {
3368 Log.v(TAG, " IntentFilter:");
3369 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3370 }
3371 if (!intent.debugCheck()) {
3372 Log.w(TAG, "==> For Activity " + a.info.name);
3373 }
3374 addFilter(intent);
3375 }
3376 }
3377
3378 public final void removeActivity(PackageParser.Activity a, String type) {
3379 mActivities.remove(a.component);
3380 if (SHOW_INFO || Config.LOGV) Log.v(
3381 TAG, " " + type + " " +
3382 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3383 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3384 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003385 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3387 if (SHOW_INFO || Config.LOGV) {
3388 Log.v(TAG, " IntentFilter:");
3389 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3390 }
3391 removeFilter(intent);
3392 }
3393 }
3394
3395 @Override
3396 protected boolean allowFilterResult(
3397 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3398 ActivityInfo filterAi = filter.activity.info;
3399 for (int i=dest.size()-1; i>=0; i--) {
3400 ActivityInfo destAi = dest.get(i).activityInfo;
3401 if (destAi.name == filterAi.name
3402 && destAi.packageName == filterAi.packageName) {
3403 return false;
3404 }
3405 }
3406 return true;
3407 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 @Override
3410 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3411 int match) {
3412 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3413 return null;
3414 }
3415 final PackageParser.Activity activity = info.activity;
3416 if (mSafeMode && (activity.info.applicationInfo.flags
3417 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3418 return null;
3419 }
3420 final ResolveInfo res = new ResolveInfo();
3421 res.activityInfo = PackageParser.generateActivityInfo(activity,
3422 mFlags);
3423 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3424 res.filter = info;
3425 }
3426 res.priority = info.getPriority();
3427 res.preferredOrder = activity.owner.mPreferredOrder;
3428 //System.out.println("Result: " + res.activityInfo.className +
3429 // " = " + res.priority);
3430 res.match = match;
3431 res.isDefault = info.hasDefault;
3432 res.labelRes = info.labelRes;
3433 res.nonLocalizedLabel = info.nonLocalizedLabel;
3434 res.icon = info.icon;
3435 return res;
3436 }
3437
3438 @Override
3439 protected void sortResults(List<ResolveInfo> results) {
3440 Collections.sort(results, mResolvePrioritySorter);
3441 }
3442
3443 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003444 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003446 out.print(prefix); out.print(
3447 Integer.toHexString(System.identityHashCode(filter.activity)));
3448 out.print(' ');
3449 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003450 }
3451
3452// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3453// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3454// final List<ResolveInfo> retList = Lists.newArrayList();
3455// while (i.hasNext()) {
3456// final ResolveInfo resolveInfo = i.next();
3457// if (isEnabledLP(resolveInfo.activityInfo)) {
3458// retList.add(resolveInfo);
3459// }
3460// }
3461// return retList;
3462// }
3463
3464 // Keys are String (activity class name), values are Activity.
3465 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3466 = new HashMap<ComponentName, PackageParser.Activity>();
3467 private int mFlags;
3468 }
3469
3470 private final class ServiceIntentResolver
3471 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003472 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003474 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003475 }
3476
Mihai Preda074edef2009-05-18 17:13:31 +02003477 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003479 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3481 }
3482
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003483 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3484 ArrayList<PackageParser.Service> packageServices) {
3485 if (packageServices == null) {
3486 return null;
3487 }
3488 mFlags = flags;
3489 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3490 int N = packageServices.size();
3491 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3492 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3493
3494 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3495 for (int i = 0; i < N; ++i) {
3496 intentFilters = packageServices.get(i).intents;
3497 if (intentFilters != null && intentFilters.size() > 0) {
3498 listCut.add(intentFilters);
3499 }
3500 }
3501 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3502 }
3503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 public final void addService(PackageParser.Service s) {
3505 mServices.put(s.component, s);
3506 if (SHOW_INFO || Config.LOGV) Log.v(
3507 TAG, " " + (s.info.nonLocalizedLabel != null
3508 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3509 if (SHOW_INFO || Config.LOGV) Log.v(
3510 TAG, " Class=" + s.info.name);
3511 int NI = s.intents.size();
3512 int j;
3513 for (j=0; j<NI; j++) {
3514 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3515 if (SHOW_INFO || Config.LOGV) {
3516 Log.v(TAG, " IntentFilter:");
3517 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3518 }
3519 if (!intent.debugCheck()) {
3520 Log.w(TAG, "==> For Service " + s.info.name);
3521 }
3522 addFilter(intent);
3523 }
3524 }
3525
3526 public final void removeService(PackageParser.Service s) {
3527 mServices.remove(s.component);
3528 if (SHOW_INFO || Config.LOGV) Log.v(
3529 TAG, " " + (s.info.nonLocalizedLabel != null
3530 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3531 if (SHOW_INFO || Config.LOGV) Log.v(
3532 TAG, " Class=" + s.info.name);
3533 int NI = s.intents.size();
3534 int j;
3535 for (j=0; j<NI; j++) {
3536 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3537 if (SHOW_INFO || Config.LOGV) {
3538 Log.v(TAG, " IntentFilter:");
3539 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3540 }
3541 removeFilter(intent);
3542 }
3543 }
3544
3545 @Override
3546 protected boolean allowFilterResult(
3547 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3548 ServiceInfo filterSi = filter.service.info;
3549 for (int i=dest.size()-1; i>=0; i--) {
3550 ServiceInfo destAi = dest.get(i).serviceInfo;
3551 if (destAi.name == filterSi.name
3552 && destAi.packageName == filterSi.packageName) {
3553 return false;
3554 }
3555 }
3556 return true;
3557 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 @Override
3560 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3561 int match) {
3562 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3563 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3564 return null;
3565 }
3566 final PackageParser.Service service = info.service;
3567 if (mSafeMode && (service.info.applicationInfo.flags
3568 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3569 return null;
3570 }
3571 final ResolveInfo res = new ResolveInfo();
3572 res.serviceInfo = PackageParser.generateServiceInfo(service,
3573 mFlags);
3574 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3575 res.filter = filter;
3576 }
3577 res.priority = info.getPriority();
3578 res.preferredOrder = service.owner.mPreferredOrder;
3579 //System.out.println("Result: " + res.activityInfo.className +
3580 // " = " + res.priority);
3581 res.match = match;
3582 res.isDefault = info.hasDefault;
3583 res.labelRes = info.labelRes;
3584 res.nonLocalizedLabel = info.nonLocalizedLabel;
3585 res.icon = info.icon;
3586 return res;
3587 }
3588
3589 @Override
3590 protected void sortResults(List<ResolveInfo> results) {
3591 Collections.sort(results, mResolvePrioritySorter);
3592 }
3593
3594 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003595 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003597 out.print(prefix); out.print(
3598 Integer.toHexString(System.identityHashCode(filter.service)));
3599 out.print(' ');
3600 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 }
3602
3603// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3604// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3605// final List<ResolveInfo> retList = Lists.newArrayList();
3606// while (i.hasNext()) {
3607// final ResolveInfo resolveInfo = (ResolveInfo) i;
3608// if (isEnabledLP(resolveInfo.serviceInfo)) {
3609// retList.add(resolveInfo);
3610// }
3611// }
3612// return retList;
3613// }
3614
3615 // Keys are String (activity class name), values are Activity.
3616 private final HashMap<ComponentName, PackageParser.Service> mServices
3617 = new HashMap<ComponentName, PackageParser.Service>();
3618 private int mFlags;
3619 };
3620
3621 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3622 new Comparator<ResolveInfo>() {
3623 public int compare(ResolveInfo r1, ResolveInfo r2) {
3624 int v1 = r1.priority;
3625 int v2 = r2.priority;
3626 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3627 if (v1 != v2) {
3628 return (v1 > v2) ? -1 : 1;
3629 }
3630 v1 = r1.preferredOrder;
3631 v2 = r2.preferredOrder;
3632 if (v1 != v2) {
3633 return (v1 > v2) ? -1 : 1;
3634 }
3635 if (r1.isDefault != r2.isDefault) {
3636 return r1.isDefault ? -1 : 1;
3637 }
3638 v1 = r1.match;
3639 v2 = r2.match;
3640 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3641 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3642 }
3643 };
3644
3645 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3646 new Comparator<ProviderInfo>() {
3647 public int compare(ProviderInfo p1, ProviderInfo p2) {
3648 final int v1 = p1.initOrder;
3649 final int v2 = p2.initOrder;
3650 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3651 }
3652 };
3653
3654 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3655 IActivityManager am = ActivityManagerNative.getDefault();
3656 if (am != null) {
3657 try {
3658 final Intent intent = new Intent(action,
3659 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3660 if (extras != null) {
3661 intent.putExtras(extras);
3662 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003663 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 am.broadcastIntent(
3665 null, intent,
3666 null, null, 0, null, null, null, false, false);
3667 } catch (RemoteException ex) {
3668 }
3669 }
3670 }
3671
3672 private final class AppDirObserver extends FileObserver {
3673 public AppDirObserver(String path, int mask, boolean isrom) {
3674 super(path, mask);
3675 mRootDir = path;
3676 mIsRom = isrom;
3677 }
3678
3679 public void onEvent(int event, String path) {
3680 String removedPackage = null;
3681 int removedUid = -1;
3682 String addedPackage = null;
3683 int addedUid = -1;
3684
3685 synchronized (mInstallLock) {
3686 String fullPathStr = null;
3687 File fullPath = null;
3688 if (path != null) {
3689 fullPath = new File(mRootDir, path);
3690 fullPathStr = fullPath.getPath();
3691 }
3692
3693 if (Config.LOGV) Log.v(
3694 TAG, "File " + fullPathStr + " changed: "
3695 + Integer.toHexString(event));
3696
3697 if (!isPackageFilename(path)) {
3698 if (Config.LOGV) Log.v(
3699 TAG, "Ignoring change of non-package file: " + fullPathStr);
3700 return;
3701 }
3702
3703 if ((event&REMOVE_EVENTS) != 0) {
3704 synchronized (mInstallLock) {
3705 PackageParser.Package p = mAppDirs.get(fullPathStr);
3706 if (p != null) {
3707 removePackageLI(p, true);
3708 removedPackage = p.applicationInfo.packageName;
3709 removedUid = p.applicationInfo.uid;
3710 }
3711 }
3712 }
3713
3714 if ((event&ADD_EVENTS) != 0) {
3715 PackageParser.Package p = mAppDirs.get(fullPathStr);
3716 if (p == null) {
3717 p = scanPackageLI(fullPath, fullPath, fullPath,
3718 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3719 PackageParser.PARSE_CHATTY |
3720 PackageParser.PARSE_MUST_BE_APK,
3721 SCAN_MONITOR);
3722 if (p != null) {
3723 synchronized (mPackages) {
3724 grantPermissionsLP(p, false);
3725 }
3726 addedPackage = p.applicationInfo.packageName;
3727 addedUid = p.applicationInfo.uid;
3728 }
3729 }
3730 }
3731
3732 synchronized (mPackages) {
3733 mSettings.writeLP();
3734 }
3735 }
3736
3737 if (removedPackage != null) {
3738 Bundle extras = new Bundle(1);
3739 extras.putInt(Intent.EXTRA_UID, removedUid);
3740 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3741 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3742 }
3743 if (addedPackage != null) {
3744 Bundle extras = new Bundle(1);
3745 extras.putInt(Intent.EXTRA_UID, addedUid);
3746 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3747 }
3748 }
3749
3750 private final String mRootDir;
3751 private final boolean mIsRom;
3752 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003754 /* Called when a downloaded package installation has been confirmed by the user */
3755 public void installPackage(
3756 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003757 installPackage(packageURI, observer, flags, null);
3758 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003759
Jacek Surazski65e13172009-04-28 15:26:38 +02003760 /* Called when a downloaded package installation has been confirmed by the user */
3761 public void installPackage(
3762 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3763 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 mContext.enforceCallingOrSelfPermission(
3765 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 // Queue up an async operation since the package installation may take a little while.
3768 mHandler.post(new Runnable() {
3769 public void run() {
3770 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003771 // Result object to be returned
3772 PackageInstalledInfo res = new PackageInstalledInfo();
3773 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3774 res.uid = -1;
3775 res.pkg = null;
3776 res.removedInfo = new PackageRemovedInfo();
3777 // Make a temporary copy of file from given packageURI
3778 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3779 if (tmpPackageFile != null) {
3780 synchronized (mInstallLock) {
3781 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003783 }
3784 if (observer != null) {
3785 try {
3786 observer.packageInstalled(res.name, res.returnCode);
3787 } catch (RemoteException e) {
3788 Log.i(TAG, "Observer no longer exists.");
3789 }
3790 }
3791 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3792 // call appears in the synchronized block above.
3793 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3794 res.removedInfo.sendBroadcast(false, true);
3795 Bundle extras = new Bundle(1);
3796 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003797 final boolean update = res.removedInfo.removedPackage != null;
3798 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3800 }
3801 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3802 res.pkg.applicationInfo.packageName,
3803 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003804 if (update) {
3805 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3806 res.pkg.applicationInfo.packageName,
3807 extras);
3808 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 }
3810 Runtime.getRuntime().gc();
3811 }
3812 });
3813 }
3814
3815 class PackageInstalledInfo {
3816 String name;
3817 int uid;
3818 PackageParser.Package pkg;
3819 int returnCode;
3820 PackageRemovedInfo removedInfo;
3821 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 /*
3824 * Install a non-existing package.
3825 */
3826 private void installNewPackageLI(String pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003827 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003829 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003830 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08003832 boolean dataDirExists;
3833
3834 if (useEncryptedFilesystemForPackage(pkg)) {
3835 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
3836 } else {
3837 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 res.name = pkgName;
3840 synchronized(mPackages) {
3841 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3842 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003843 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003844 + " without first uninstalling.");
3845 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3846 return;
3847 }
3848 }
3849 if (destPackageFile.exists()) {
3850 // It's safe to do this because we know (from the above check) that the file
3851 // isn't currently used for an installed package.
3852 destPackageFile.delete();
3853 }
3854 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3855 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3856 destResourceFile, pkg, 0,
3857 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003858 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003859 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3860 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 if (newPackage == null) {
3862 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3863 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3864 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3865 }
3866 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003867 updateSettingsLI(pkgName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003869 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003870 newPackage,
3871 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003872 forwardLocked,
3873 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003874 res);
3875 // delete the partially installed application. the data directory will have to be
3876 // restored if it was already existing
3877 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3878 // remove package from internal structures. Note that we want deletePackageX to
3879 // delete the package data and cache directories that it created in
3880 // scanPackageLocked, unless those directories existed before we even tried to
3881 // install.
3882 deletePackageLI(
3883 pkgName, true,
3884 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3885 res.removedInfo);
3886 }
3887 }
3888 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 private void replacePackageLI(String pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003891 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003892 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003893 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003894 String installerPackageName, PackageInstalledInfo res) {
3895
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003896 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 // First find the old package info and check signatures
3898 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003899 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003900 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3901 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003902 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3903 return;
3904 }
3905 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003906 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003907 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003908 replaceSystemPackageLI(oldPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003909 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003910 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003911 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003912 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003913 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003914 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003915 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 }
3917 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003920 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003921 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003922 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003923 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 PackageParser.Package newPackage = null;
3925 String pkgName = deletedPackage.packageName;
3926 boolean deletedPkg = true;
3927 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003928
Jacek Surazski65e13172009-04-28 15:26:38 +02003929 String oldInstallerPackageName = null;
3930 synchronized (mPackages) {
3931 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003933
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003934 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 // First delete the existing package while retaining the data directory
3936 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3937 res.removedInfo)) {
3938 // If the existing package was'nt successfully deleted
3939 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3940 deletedPkg = false;
3941 } else {
3942 // Successfully deleted the old package. Now proceed with re-installation
3943 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3944 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3945 destResourceFile, pkg, parseFlags,
3946 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003947 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003948 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3949 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003950 if (newPackage == null) {
3951 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3952 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3953 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3954 }
3955 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003956 updateSettingsLI(pkgName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003957 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003958 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 newPackage,
3960 true,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003961 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003962 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003963 res);
3964 updatedSettings = true;
3965 }
3966 }
3967
3968 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3969 // If we deleted an exisiting package, the old source and resource files that we
3970 // were keeping around in case we needed them (see below) can now be deleted
3971 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3972 final ApplicationInfo installedPackageAppInfo =
3973 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003974 deletePackageResourcesLI(pkgName,
3975 !deletedPackageAppInfo.sourceDir
3976 .equals(installedPackageAppInfo.sourceDir)
3977 ? deletedPackageAppInfo.sourceDir : null,
3978 !deletedPackageAppInfo.publicSourceDir
3979 .equals(installedPackageAppInfo.publicSourceDir)
3980 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003981 //update signature on the new package setting
3982 //this should always succeed, since we checked the
3983 //signature earlier.
3984 synchronized(mPackages) {
3985 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3986 parseFlags, true);
3987 }
3988 } else {
3989 // remove package from internal structures. Note that we want deletePackageX to
3990 // delete the package data and cache directories that it created in
3991 // scanPackageLocked, unless those directories existed before we even tried to
3992 // install.
3993 if(updatedSettings) {
3994 deletePackageLI(
3995 pkgName, true,
3996 PackageManager.DONT_DELETE_DATA,
3997 res.removedInfo);
3998 }
3999 // Since we failed to install the new package we need to restore the old
4000 // package that we deleted.
4001 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004002 File restoreFile = new File(deletedPackage.mPath);
4003 if (restoreFile == null) {
4004 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4005 return;
4006 }
4007 File restoreTmpFile = createTempPackageFile();
4008 if (restoreTmpFile == null) {
4009 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
4010 return;
4011 }
4012 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
4013 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
4014 return;
4015 }
4016 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4017 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004019 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004021 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004022 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
4023 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4024 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 }
4027 }
4028 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004030 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004031 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07004033 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02004034 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 PackageParser.Package newPackage = null;
4036 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004037 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004038 PackageParser.PARSE_IS_SYSTEM;
4039 String packageName = deletedPackage.packageName;
4040 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4041 if (packageName == null) {
4042 Log.w(TAG, "Attempt to delete null packageName.");
4043 return;
4044 }
4045 PackageParser.Package oldPkg;
4046 PackageSetting oldPkgSetting;
4047 synchronized (mPackages) {
4048 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004049 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4051 (oldPkgSetting == null)) {
4052 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4053 return;
4054 }
4055 }
4056 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4057 res.removedInfo.removedPackage = packageName;
4058 // Remove existing system package
4059 removePackageLI(oldPkg, true);
4060 synchronized (mPackages) {
4061 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4062 }
4063
4064 // Successfully disabled the old package. Now proceed with re-installation
4065 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4066 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
4067 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
4068 destResourceFile, pkg, parseFlags,
4069 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004070 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07004071 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
4072 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 if (newPackage == null) {
4074 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
4075 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4076 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4077 }
4078 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004079 updateSettingsLI(packageName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004080 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004081 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 newPackage,
4083 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02004084 forwardLocked,
4085 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 res);
4087 updatedSettings = true;
4088 }
4089
4090 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4091 //update signature on the new package setting
4092 //this should always succeed, since we checked the
4093 //signature earlier.
4094 synchronized(mPackages) {
4095 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4096 parseFlags, true);
4097 }
4098 } else {
4099 // Re installation failed. Restore old information
4100 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004101 if (newPackage != null) {
4102 removePackageLI(newPackage, true);
4103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 // Add back the old system package
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004105 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 oldPkgSetting.resourcePath,
4107 oldPkg, parseFlags,
4108 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004109 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 // Restore the old system information in Settings
4111 synchronized(mPackages) {
4112 if(updatedSettings) {
4113 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004114 mSettings.setInstallerPackageName(packageName,
4115 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004116 }
4117 mSettings.writeLP();
4118 }
4119 }
4120 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004121
4122 private void updateSettingsLI(String pkgName, File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 String destFilePath, File destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004124 File destResourceFile,
4125 PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004126 PackageParser.Package newPackage,
4127 boolean replacingExistingPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004128 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004129 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 synchronized (mPackages) {
4131 //write settings. the installStatus will be incomplete at this stage.
4132 //note that the new package setting would have already been
4133 //added to mPackages. It hasn't been persisted yet.
4134 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4135 mSettings.writeLP();
4136 }
4137
4138 int retCode = 0;
4139 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4140 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4141 destPackageFile.toString());
4142 if (retCode != 0) {
4143 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4144 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4145 return;
4146 }
4147 }
4148 // XXX There are probably some big issues here: upon doing
4149 // the rename, we have reached the point of no return (the
4150 // original .apk is gone!), so we can't fail. Yet... we can.
4151 if (!tmpPackageFile.renameTo(destPackageFile)) {
4152 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4153 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4154 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004155 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4156 destResourceFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 forwardLocked);
4158 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4159 return;
4160 } else {
4161 Log.d(TAG, "New package installed in " + destPackageFile);
4162 }
4163 }
4164 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4165 if (mInstaller != null) {
4166 mInstaller.rmdex(tmpPackageFile.getPath());
4167 }
4168 }
4169
4170 synchronized (mPackages) {
4171 grantPermissionsLP(newPackage, true);
4172 res.name = pkgName;
4173 res.uid = newPackage.applicationInfo.uid;
4174 res.pkg = newPackage;
4175 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004176 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4178 //to update install status
4179 mSettings.writeLP();
4180 }
4181 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004182
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004183 private File getFwdLockedResource(String pkgName) {
4184 final String publicZipFileName = pkgName + ".zip";
4185 return new File(mAppInstallDir, publicZipFileName);
4186 }
4187
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004188 private File copyTempInstallFile(Uri pPackageURI,
4189 PackageInstalledInfo res) {
4190 File tmpPackageFile = createTempPackageFile();
4191 int retCode = PackageManager.INSTALL_SUCCEEDED;
4192 if (tmpPackageFile == null) {
4193 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4194 return null;
4195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004197 if (pPackageURI.getScheme().equals("file")) {
4198 final File srcPackageFile = new File(pPackageURI.getPath());
4199 // We copy the source package file to a temp file and then rename it to the
4200 // destination file in order to eliminate a window where the package directory
4201 // scanner notices the new package file but it's not completely copied yet.
4202 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4203 Log.e(TAG, "Couldn't copy package file to temp file.");
4204 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004206 } else if (pPackageURI.getScheme().equals("content")) {
4207 ParcelFileDescriptor fd = null;
4208 try {
4209 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4210 } catch (FileNotFoundException e) {
4211 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4212 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4213 }
4214 if (fd == null) {
4215 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4216 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4217 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 if (Config.LOGV) {
4219 Log.v(TAG, "Opened file descriptor from download service.");
4220 }
4221 ParcelFileDescriptor.AutoCloseInputStream
4222 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4223 // We copy the source package file to a temp file and then rename it to the
4224 // destination file in order to eliminate a window where the package directory
4225 // scanner notices the new package file but it's not completely copied yet.
4226 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4227 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004228 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004231 } else {
4232 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4233 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4234 }
4235
4236 res.returnCode = retCode;
4237 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4238 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4239 tmpPackageFile.delete();
4240 }
4241 return null;
4242 }
4243 return tmpPackageFile;
4244 }
4245
4246 private void installPackageLI(Uri pPackageURI,
4247 int pFlags, boolean newInstall, String installerPackageName,
4248 File tmpPackageFile, PackageInstalledInfo res) {
4249 String pkgName = null;
4250 boolean forwardLocked = false;
4251 boolean replacingExistingPackage = false;
4252 // Result object to be returned
4253 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4254
4255 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004256 pkgName = PackageParser.parsePackageName(
4257 tmpPackageFile.getAbsolutePath(), 0);
4258 if (pkgName == null) {
4259 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4260 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4261 break main_flow;
4262 }
4263 res.name = pkgName;
4264 //initialize some variables before installing pkg
4265 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004266 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 ? mDrmAppPrivateInstallDir
4268 : mAppInstallDir;
4269 final File destPackageFile = new File(destDir, pkgFileName);
4270 final String destFilePath = destPackageFile.getAbsolutePath();
4271 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004272 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004273 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 forwardLocked = true;
4275 } else {
4276 destResourceFile = destPackageFile;
4277 }
4278 // Retrieve PackageSettings and parse package
4279 int parseFlags = PackageParser.PARSE_CHATTY;
4280 parseFlags |= mDefParseFlags;
4281 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4282 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4284 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4285 if (pkg == null) {
4286 res.returnCode = pp.getParseError();
4287 break main_flow;
4288 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004289 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4290 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4291 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4292 break main_flow;
4293 }
4294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004295 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4296 res.returnCode = pp.getParseError();
4297 break main_flow;
4298 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 synchronized (mPackages) {
4301 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004302 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 && mPackages.containsKey(pkgName)) {
4304 replacingExistingPackage = true;
4305 }
4306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 if(replacingExistingPackage) {
4309 replacePackageLI(pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004310 tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004311 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004312 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 res);
4314 } else {
4315 installNewPackageLI(pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004316 tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004318 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004319 res);
4320 }
4321 } finally {
4322 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4323 tmpPackageFile.delete();
4324 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 }
4326 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004328 private int setPermissionsLI(String pkgName,
4329 PackageParser.Package newPackage,
4330 String destFilePath,
4331 File destResourceFile,
4332 boolean forwardLocked) {
4333 int retCode;
4334 if (forwardLocked) {
4335 try {
4336 extractPublicFiles(newPackage, destResourceFile);
4337 } catch (IOException e) {
4338 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4339 " forward-locked app.");
4340 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4341 } finally {
4342 //TODO clean up the extracted public files
4343 }
4344 if (mInstaller != null) {
4345 retCode = mInstaller.setForwardLockPerm(pkgName,
4346 newPackage.applicationInfo.uid);
4347 } else {
4348 final int filePermissions =
4349 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4350 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4351 newPackage.applicationInfo.uid);
4352 }
4353 } else {
4354 final int filePermissions =
4355 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4356 |FileUtils.S_IROTH;
4357 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4358 }
4359 if (retCode != 0) {
4360 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4361 + ". The return code was: " + retCode);
4362 }
4363 return PackageManager.INSTALL_SUCCEEDED;
4364 }
4365
4366 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4367 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4368 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4369 }
4370
4371 private void extractPublicFiles(PackageParser.Package newPackage,
4372 File publicZipFile) throws IOException {
4373 final ZipOutputStream publicZipOutStream =
4374 new ZipOutputStream(new FileOutputStream(publicZipFile));
4375 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4376
4377 // Copy manifest, resources.arsc and res directory to public zip
4378
4379 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4380 while (privateZipEntries.hasMoreElements()) {
4381 final ZipEntry zipEntry = privateZipEntries.nextElement();
4382 final String zipEntryName = zipEntry.getName();
4383 if ("AndroidManifest.xml".equals(zipEntryName)
4384 || "resources.arsc".equals(zipEntryName)
4385 || zipEntryName.startsWith("res/")) {
4386 try {
4387 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4388 } catch (IOException e) {
4389 try {
4390 publicZipOutStream.close();
4391 throw e;
4392 } finally {
4393 publicZipFile.delete();
4394 }
4395 }
4396 }
4397 }
4398
4399 publicZipOutStream.close();
4400 FileUtils.setPermissions(
4401 publicZipFile.getAbsolutePath(),
4402 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4403 -1, -1);
4404 }
4405
4406 private static void copyZipEntry(ZipEntry zipEntry,
4407 ZipFile inZipFile,
4408 ZipOutputStream outZipStream) throws IOException {
4409 byte[] buffer = new byte[4096];
4410 int num;
4411
4412 ZipEntry newEntry;
4413 if (zipEntry.getMethod() == ZipEntry.STORED) {
4414 // Preserve the STORED method of the input entry.
4415 newEntry = new ZipEntry(zipEntry);
4416 } else {
4417 // Create a new entry so that the compressed len is recomputed.
4418 newEntry = new ZipEntry(zipEntry.getName());
4419 }
4420 outZipStream.putNextEntry(newEntry);
4421
4422 InputStream data = inZipFile.getInputStream(zipEntry);
4423 while ((num = data.read(buffer)) > 0) {
4424 outZipStream.write(buffer, 0, num);
4425 }
4426 outZipStream.flush();
4427 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004429 private void deleteTempPackageFiles() {
4430 FilenameFilter filter = new FilenameFilter() {
4431 public boolean accept(File dir, String name) {
4432 return name.startsWith("vmdl") && name.endsWith(".tmp");
4433 }
4434 };
4435 String tmpFilesList[] = mAppInstallDir.list(filter);
4436 if(tmpFilesList == null) {
4437 return;
4438 }
4439 for(int i = 0; i < tmpFilesList.length; i++) {
4440 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4441 tmpFile.delete();
4442 }
4443 }
4444
4445 private File createTempPackageFile() {
4446 File tmpPackageFile;
4447 try {
4448 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4449 } catch (IOException e) {
4450 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4451 return null;
4452 }
4453 try {
4454 FileUtils.setPermissions(
4455 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4456 -1, -1);
4457 } catch (IOException e) {
4458 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4459 return null;
4460 }
4461 return tmpPackageFile;
4462 }
4463
4464 public void deletePackage(final String packageName,
4465 final IPackageDeleteObserver observer,
4466 final int flags) {
4467 mContext.enforceCallingOrSelfPermission(
4468 android.Manifest.permission.DELETE_PACKAGES, null);
4469 // Queue up an async operation since the package deletion may take a little while.
4470 mHandler.post(new Runnable() {
4471 public void run() {
4472 mHandler.removeCallbacks(this);
4473 final boolean succeded = deletePackageX(packageName, true, true, flags);
4474 if (observer != null) {
4475 try {
4476 observer.packageDeleted(succeded);
4477 } catch (RemoteException e) {
4478 Log.i(TAG, "Observer no longer exists.");
4479 } //end catch
4480 } //end if
4481 } //end run
4482 });
4483 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 /**
4486 * This method is an internal method that could be get invoked either
4487 * to delete an installed package or to clean up a failed installation.
4488 * After deleting an installed package, a broadcast is sent to notify any
4489 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004490 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004491 * installation wouldn't have sent the initial broadcast either
4492 * The key steps in deleting a package are
4493 * deleting the package information in internal structures like mPackages,
4494 * deleting the packages base directories through installd
4495 * updating mSettings to reflect current status
4496 * persisting settings for later use
4497 * sending a broadcast if necessary
4498 */
4499
4500 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4501 boolean deleteCodeAndResources, int flags) {
4502 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004503 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504
4505 synchronized (mInstallLock) {
4506 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4507 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004509 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004510 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4511 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4512
4513 // If the removed package was a system update, the old system packaged
4514 // was re-enabled; we need to broadcast this information
4515 if (systemUpdate) {
4516 Bundle extras = new Bundle(1);
4517 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4518 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4519
4520 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4521 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 }
4524 return res;
4525 }
4526
4527 static class PackageRemovedInfo {
4528 String removedPackage;
4529 int uid = -1;
4530 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004531 boolean isRemovedPackageSystemUpdate = false;
4532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 void sendBroadcast(boolean fullRemove, boolean replacing) {
4534 Bundle extras = new Bundle(1);
4535 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4536 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4537 if (replacing) {
4538 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4539 }
4540 if (removedPackage != null) {
4541 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4542 }
4543 if (removedUid >= 0) {
4544 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4545 }
4546 }
4547 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004549 /*
4550 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4551 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004552 * 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 -08004553 * delete a partially installed application.
4554 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004555 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 int flags) {
4557 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004558 if (outInfo != null) {
4559 outInfo.removedPackage = packageName;
4560 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 removePackageLI(p, true);
4562 // Retrieve object to delete permissions for shared user later on
4563 PackageSetting deletedPs;
4564 synchronized (mPackages) {
4565 deletedPs = mSettings.mPackages.get(packageName);
4566 }
4567 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004568 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004569 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004570 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004571 if (retCode < 0) {
4572 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4573 + packageName + ", retcode=" + retCode);
4574 // we don't consider this to be a failure of the core package deletion
4575 }
4576 } else {
4577 //for emulator
4578 PackageParser.Package pkg = mPackages.get(packageName);
4579 File dataDir = new File(pkg.applicationInfo.dataDir);
4580 dataDir.delete();
4581 }
4582 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004583 if (outInfo != null) {
4584 outInfo.removedUid = mSettings.removePackageLP(packageName);
4585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
4587 }
4588 synchronized (mPackages) {
4589 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4590 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004591 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004592 }
4593 // Save settings now
4594 mSettings.writeLP ();
4595 }
4596 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 /*
4599 * Tries to delete system package.
4600 */
4601 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004602 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 ApplicationInfo applicationInfo = p.applicationInfo;
4604 //applicable for non-partially installed applications only
4605 if (applicationInfo == null) {
4606 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4607 return false;
4608 }
4609 PackageSetting ps = null;
4610 // Confirm if the system package has been updated
4611 // An updated system app can be deleted. This will also have to restore
4612 // the system pkg from system partition
4613 synchronized (mPackages) {
4614 ps = mSettings.getDisabledSystemPkg(p.packageName);
4615 }
4616 if (ps == null) {
4617 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4618 return false;
4619 } else {
4620 Log.i(TAG, "Deleting system pkg from data partition");
4621 }
4622 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004623 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004624 boolean deleteCodeAndResources = false;
4625 if (ps.versionCode < p.mVersionCode) {
4626 // Delete code and resources for downgrades
4627 deleteCodeAndResources = true;
4628 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4629 flags &= ~PackageManager.DONT_DELETE_DATA;
4630 }
4631 } else {
4632 // Preserve data by setting flag
4633 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4634 flags |= PackageManager.DONT_DELETE_DATA;
4635 }
4636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004637 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4638 if (!ret) {
4639 return false;
4640 }
4641 synchronized (mPackages) {
4642 // Reinstate the old system package
4643 mSettings.enableSystemPackageLP(p.packageName);
4644 }
4645 // Install the system package
4646 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4647 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4648 SCAN_MONITOR);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 if (newPkg == null) {
4651 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4652 return false;
4653 }
4654 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004655 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004656 mSettings.writeLP();
4657 }
4658 return true;
4659 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004660
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004661 private void deletePackageResourcesLI(String packageName,
4662 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004663 if (sourceDir != null) {
4664 File sourceFile = new File(sourceDir);
4665 if (!sourceFile.exists()) {
4666 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4667 }
4668 // Delete application's code and resources
4669 sourceFile.delete();
4670 if (mInstaller != null) {
4671 int retCode = mInstaller.rmdex(sourceFile.toString());
4672 if (retCode < 0) {
4673 Log.w(TAG, "Couldn't remove dex file for package: "
4674 + packageName + " at location "
4675 + sourceFile.toString() + ", retcode=" + retCode);
4676 // we don't consider this to be a failure of the core package deletion
4677 }
4678 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004679 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004680 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4681 final File publicSourceFile = new File(publicSourceDir);
4682 if (!publicSourceFile.exists()) {
4683 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4684 }
4685 if (publicSourceFile.exists()) {
4686 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004687 }
4688 }
4689 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4692 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4693 ApplicationInfo applicationInfo = p.applicationInfo;
4694 if (applicationInfo == null) {
4695 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4696 return false;
4697 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004698 if (outInfo != null) {
4699 outInfo.uid = applicationInfo.uid;
4700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701
4702 // Delete package data from internal structures and also remove data if flag is set
4703 removePackageDataLI(p, outInfo, flags);
4704
4705 // Delete application code and resources
4706 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004707 deletePackageResourcesLI(applicationInfo.packageName,
4708 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004709 }
4710 return true;
4711 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 /*
4714 * This method handles package deletion in general
4715 */
4716 private boolean deletePackageLI(String packageName,
4717 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4718 if (packageName == null) {
4719 Log.w(TAG, "Attempt to delete null packageName.");
4720 return false;
4721 }
4722 PackageParser.Package p;
4723 boolean dataOnly = false;
4724 synchronized (mPackages) {
4725 p = mPackages.get(packageName);
4726 if (p == null) {
4727 //this retrieves partially installed apps
4728 dataOnly = true;
4729 PackageSetting ps = mSettings.mPackages.get(packageName);
4730 if (ps == null) {
4731 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4732 return false;
4733 }
4734 p = ps.pkg;
4735 }
4736 }
4737 if (p == null) {
4738 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4739 return false;
4740 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 if (dataOnly) {
4743 // Delete application data first
4744 removePackageDataLI(p, outInfo, flags);
4745 return true;
4746 }
4747 // At this point the package should have ApplicationInfo associated with it
4748 if (p.applicationInfo == null) {
4749 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4750 return false;
4751 }
4752 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4753 Log.i(TAG, "Removing system package:"+p.packageName);
4754 // When an updated system application is deleted we delete the existing resources as well and
4755 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004756 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 }
4758 Log.i(TAG, "Removing non-system package:"+p.packageName);
4759 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4760 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 public void clearApplicationUserData(final String packageName,
4763 final IPackageDataObserver observer) {
4764 mContext.enforceCallingOrSelfPermission(
4765 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4766 // Queue up an async operation since the package deletion may take a little while.
4767 mHandler.post(new Runnable() {
4768 public void run() {
4769 mHandler.removeCallbacks(this);
4770 final boolean succeeded;
4771 synchronized (mInstallLock) {
4772 succeeded = clearApplicationUserDataLI(packageName);
4773 }
4774 if (succeeded) {
4775 // invoke DeviceStorageMonitor's update method to clear any notifications
4776 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4777 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4778 if (dsm != null) {
4779 dsm.updateMemory();
4780 }
4781 }
4782 if(observer != null) {
4783 try {
4784 observer.onRemoveCompleted(packageName, succeeded);
4785 } catch (RemoteException e) {
4786 Log.i(TAG, "Observer no longer exists.");
4787 }
4788 } //end if observer
4789 } //end run
4790 });
4791 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004793 private boolean clearApplicationUserDataLI(String packageName) {
4794 if (packageName == null) {
4795 Log.w(TAG, "Attempt to delete null packageName.");
4796 return false;
4797 }
4798 PackageParser.Package p;
4799 boolean dataOnly = false;
4800 synchronized (mPackages) {
4801 p = mPackages.get(packageName);
4802 if(p == null) {
4803 dataOnly = true;
4804 PackageSetting ps = mSettings.mPackages.get(packageName);
4805 if((ps == null) || (ps.pkg == null)) {
4806 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4807 return false;
4808 }
4809 p = ps.pkg;
4810 }
4811 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004812 boolean useEncryptedFSDir = false;
4813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 if(!dataOnly) {
4815 //need to check this only for fully installed applications
4816 if (p == null) {
4817 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4818 return false;
4819 }
4820 final ApplicationInfo applicationInfo = p.applicationInfo;
4821 if (applicationInfo == null) {
4822 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4823 return false;
4824 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004825 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 }
4827 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004828 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004829 if (retCode < 0) {
4830 Log.w(TAG, "Couldn't remove cache files for package: "
4831 + packageName);
4832 return false;
4833 }
4834 }
4835 return true;
4836 }
4837
4838 public void deleteApplicationCacheFiles(final String packageName,
4839 final IPackageDataObserver observer) {
4840 mContext.enforceCallingOrSelfPermission(
4841 android.Manifest.permission.DELETE_CACHE_FILES, null);
4842 // Queue up an async operation since the package deletion may take a little while.
4843 mHandler.post(new Runnable() {
4844 public void run() {
4845 mHandler.removeCallbacks(this);
4846 final boolean succeded;
4847 synchronized (mInstallLock) {
4848 succeded = deleteApplicationCacheFilesLI(packageName);
4849 }
4850 if(observer != null) {
4851 try {
4852 observer.onRemoveCompleted(packageName, succeded);
4853 } catch (RemoteException e) {
4854 Log.i(TAG, "Observer no longer exists.");
4855 }
4856 } //end if observer
4857 } //end run
4858 });
4859 }
4860
4861 private boolean deleteApplicationCacheFilesLI(String packageName) {
4862 if (packageName == null) {
4863 Log.w(TAG, "Attempt to delete null packageName.");
4864 return false;
4865 }
4866 PackageParser.Package p;
4867 synchronized (mPackages) {
4868 p = mPackages.get(packageName);
4869 }
4870 if (p == null) {
4871 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4872 return false;
4873 }
4874 final ApplicationInfo applicationInfo = p.applicationInfo;
4875 if (applicationInfo == null) {
4876 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4877 return false;
4878 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004879 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08004881 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882 if (retCode < 0) {
4883 Log.w(TAG, "Couldn't remove cache files for package: "
4884 + packageName);
4885 return false;
4886 }
4887 }
4888 return true;
4889 }
4890
4891 public void getPackageSizeInfo(final String packageName,
4892 final IPackageStatsObserver observer) {
4893 mContext.enforceCallingOrSelfPermission(
4894 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4895 // Queue up an async operation since the package deletion may take a little while.
4896 mHandler.post(new Runnable() {
4897 public void run() {
4898 mHandler.removeCallbacks(this);
4899 PackageStats lStats = new PackageStats(packageName);
4900 final boolean succeded;
4901 synchronized (mInstallLock) {
4902 succeded = getPackageSizeInfoLI(packageName, lStats);
4903 }
4904 if(observer != null) {
4905 try {
4906 observer.onGetStatsCompleted(lStats, succeded);
4907 } catch (RemoteException e) {
4908 Log.i(TAG, "Observer no longer exists.");
4909 }
4910 } //end if observer
4911 } //end run
4912 });
4913 }
4914
4915 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4916 if (packageName == null) {
4917 Log.w(TAG, "Attempt to get size of null packageName.");
4918 return false;
4919 }
4920 PackageParser.Package p;
4921 boolean dataOnly = false;
4922 synchronized (mPackages) {
4923 p = mPackages.get(packageName);
4924 if(p == null) {
4925 dataOnly = true;
4926 PackageSetting ps = mSettings.mPackages.get(packageName);
4927 if((ps == null) || (ps.pkg == null)) {
4928 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4929 return false;
4930 }
4931 p = ps.pkg;
4932 }
4933 }
4934 String publicSrcDir = null;
4935 if(!dataOnly) {
4936 final ApplicationInfo applicationInfo = p.applicationInfo;
4937 if (applicationInfo == null) {
4938 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4939 return false;
4940 }
4941 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4942 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08004943 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004944 if (mInstaller != null) {
4945 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08004946 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 if (res < 0) {
4948 return false;
4949 } else {
4950 return true;
4951 }
4952 }
4953 return true;
4954 }
4955
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 public void addPackageToPreferred(String packageName) {
4958 mContext.enforceCallingOrSelfPermission(
4959 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004960 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004961 }
4962
4963 public void removePackageFromPreferred(String packageName) {
4964 mContext.enforceCallingOrSelfPermission(
4965 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004966 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 }
4968
4969 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004970 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004971 }
4972
4973 public void addPreferredActivity(IntentFilter filter, int match,
4974 ComponentName[] set, ComponentName activity) {
4975 mContext.enforceCallingOrSelfPermission(
4976 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4977
4978 synchronized (mPackages) {
4979 Log.i(TAG, "Adding preferred activity " + activity + ":");
4980 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4981 mSettings.mPreferredActivities.addFilter(
4982 new PreferredActivity(filter, match, set, activity));
4983 mSettings.writeLP();
4984 }
4985 }
4986
Satish Sampath8dbe6122009-06-02 23:35:54 +01004987 public void replacePreferredActivity(IntentFilter filter, int match,
4988 ComponentName[] set, ComponentName activity) {
4989 mContext.enforceCallingOrSelfPermission(
4990 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4991 if (filter.countActions() != 1) {
4992 throw new IllegalArgumentException(
4993 "replacePreferredActivity expects filter to have only 1 action.");
4994 }
4995 if (filter.countCategories() != 1) {
4996 throw new IllegalArgumentException(
4997 "replacePreferredActivity expects filter to have only 1 category.");
4998 }
4999 if (filter.countDataAuthorities() != 0
5000 || filter.countDataPaths() != 0
5001 || filter.countDataSchemes() != 0
5002 || filter.countDataTypes() != 0) {
5003 throw new IllegalArgumentException(
5004 "replacePreferredActivity expects filter to have no data authorities, " +
5005 "paths, schemes or types.");
5006 }
5007 synchronized (mPackages) {
5008 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5009 String action = filter.getAction(0);
5010 String category = filter.getCategory(0);
5011 while (it.hasNext()) {
5012 PreferredActivity pa = it.next();
5013 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5014 it.remove();
5015 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5016 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5017 }
5018 }
5019 addPreferredActivity(filter, match, set, activity);
5020 }
5021 }
5022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005023 public void clearPackagePreferredActivities(String packageName) {
5024 mContext.enforceCallingOrSelfPermission(
5025 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5026
5027 synchronized (mPackages) {
5028 if (clearPackagePreferredActivitiesLP(packageName)) {
5029 mSettings.writeLP();
5030 }
5031 }
5032 }
5033
5034 boolean clearPackagePreferredActivitiesLP(String packageName) {
5035 boolean changed = false;
5036 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5037 while (it.hasNext()) {
5038 PreferredActivity pa = it.next();
5039 if (pa.mActivity.getPackageName().equals(packageName)) {
5040 it.remove();
5041 changed = true;
5042 }
5043 }
5044 return changed;
5045 }
5046
5047 public int getPreferredActivities(List<IntentFilter> outFilters,
5048 List<ComponentName> outActivities, String packageName) {
5049
5050 int num = 0;
5051 synchronized (mPackages) {
5052 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5053 while (it.hasNext()) {
5054 PreferredActivity pa = it.next();
5055 if (packageName == null
5056 || pa.mActivity.getPackageName().equals(packageName)) {
5057 if (outFilters != null) {
5058 outFilters.add(new IntentFilter(pa));
5059 }
5060 if (outActivities != null) {
5061 outActivities.add(pa.mActivity);
5062 }
5063 }
5064 }
5065 }
5066
5067 return num;
5068 }
5069
5070 public void setApplicationEnabledSetting(String appPackageName,
5071 int newState, int flags) {
5072 setEnabledSetting(appPackageName, null, newState, flags);
5073 }
5074
5075 public void setComponentEnabledSetting(ComponentName componentName,
5076 int newState, int flags) {
5077 setEnabledSetting(componentName.getPackageName(),
5078 componentName.getClassName(), newState, flags);
5079 }
5080
5081 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005082 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5084 || newState == COMPONENT_ENABLED_STATE_ENABLED
5085 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5086 throw new IllegalArgumentException("Invalid new component state: "
5087 + newState);
5088 }
5089 PackageSetting pkgSetting;
5090 final int uid = Binder.getCallingUid();
5091 final int permission = mContext.checkCallingPermission(
5092 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5093 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005094 boolean sendNow = false;
5095 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005096 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005098 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005100 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005101 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005102 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005104 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 }
5106 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005107 "Unknown component: " + packageName
5108 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005109 }
5110 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5111 throw new SecurityException(
5112 "Permission Denial: attempt to change component state from pid="
5113 + Binder.getCallingPid()
5114 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5115 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005116 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005117 // We're dealing with an application/package level state change
5118 pkgSetting.enabled = newState;
5119 } else {
5120 // We're dealing with a component level state change
5121 switch (newState) {
5122 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005123 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 break;
5125 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005126 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 break;
5128 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005129 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 break;
5131 default:
5132 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005133 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 }
5135 }
5136 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005137 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005138 components = mPendingBroadcasts.get(packageName);
5139 boolean newPackage = components == null;
5140 if (newPackage) {
5141 components = new ArrayList<String>();
5142 }
5143 if (!components.contains(componentName)) {
5144 components.add(componentName);
5145 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005146 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5147 sendNow = true;
5148 // Purge entry from pending broadcast list if another one exists already
5149 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005150 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005151 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005152 if (newPackage) {
5153 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005154 }
5155 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5156 // Schedule a message
5157 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5158 }
5159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005162 long callingId = Binder.clearCallingIdentity();
5163 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005164 if (sendNow) {
5165 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005166 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005168 } finally {
5169 Binder.restoreCallingIdentity(callingId);
5170 }
5171 }
5172
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005173 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005174 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5175 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5176 + " components=" + componentNames);
5177 Bundle extras = new Bundle(4);
5178 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5179 String nameList[] = new String[componentNames.size()];
5180 componentNames.toArray(nameList);
5181 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005182 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5183 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005184 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005185 }
5186
Jacek Surazski65e13172009-04-28 15:26:38 +02005187 public String getInstallerPackageName(String packageName) {
5188 synchronized (mPackages) {
5189 PackageSetting pkg = mSettings.mPackages.get(packageName);
5190 if (pkg == null) {
5191 throw new IllegalArgumentException("Unknown package: " + packageName);
5192 }
5193 return pkg.installerPackageName;
5194 }
5195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 public int getApplicationEnabledSetting(String appPackageName) {
5198 synchronized (mPackages) {
5199 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5200 if (pkg == null) {
5201 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5202 }
5203 return pkg.enabled;
5204 }
5205 }
5206
5207 public int getComponentEnabledSetting(ComponentName componentName) {
5208 synchronized (mPackages) {
5209 final String packageNameStr = componentName.getPackageName();
5210 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5211 if (pkg == null) {
5212 throw new IllegalArgumentException("Unknown component: " + componentName);
5213 }
5214 final String classNameStr = componentName.getClassName();
5215 return pkg.currentEnabledStateLP(classNameStr);
5216 }
5217 }
5218
5219 public void enterSafeMode() {
5220 if (!mSystemReady) {
5221 mSafeMode = true;
5222 }
5223 }
5224
5225 public void systemReady() {
5226 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005227
5228 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005229 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005230 mContext.getContentResolver(),
5231 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005232 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005233 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005234 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 }
5237
5238 public boolean isSafeMode() {
5239 return mSafeMode;
5240 }
5241
5242 public boolean hasSystemUidErrors() {
5243 return mHasSystemUidErrors;
5244 }
5245
5246 static String arrayToString(int[] array) {
5247 StringBuffer buf = new StringBuffer(128);
5248 buf.append('[');
5249 if (array != null) {
5250 for (int i=0; i<array.length; i++) {
5251 if (i > 0) buf.append(", ");
5252 buf.append(array[i]);
5253 }
5254 }
5255 buf.append(']');
5256 return buf.toString();
5257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 @Override
5260 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5261 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5262 != PackageManager.PERMISSION_GRANTED) {
5263 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5264 + Binder.getCallingPid()
5265 + ", uid=" + Binder.getCallingUid()
5266 + " without permission "
5267 + android.Manifest.permission.DUMP);
5268 return;
5269 }
5270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 synchronized (mPackages) {
5272 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005273 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005274 pw.println(" ");
5275 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005276 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 pw.println(" ");
5278 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005279 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005280 pw.println(" ");
5281 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005282 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 pw.println("Permissions:");
5285 {
5286 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005287 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5288 pw.print(Integer.toHexString(System.identityHashCode(p)));
5289 pw.println("):");
5290 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5291 pw.print(" uid="); pw.print(p.uid);
5292 pw.print(" gids="); pw.print(arrayToString(p.gids));
5293 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 }
5295 }
5296 pw.println(" ");
5297 pw.println("Packages:");
5298 {
5299 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005300 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5301 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5302 pw.println("):");
5303 pw.print(" userId="); pw.print(ps.userId);
5304 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5305 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5306 pw.print(" pkg="); pw.println(ps.pkg);
5307 pw.print(" codePath="); pw.println(ps.codePathString);
5308 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005309 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005310 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005311 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005312 pw.print(" supportsScreens=[");
5313 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005314 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005315 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005316 if (!first) pw.print(", ");
5317 first = false;
5318 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005320 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005321 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005322 if (!first) pw.print(", ");
5323 first = false;
5324 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005325 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005326 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005327 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005328 if (!first) pw.print(", ");
5329 first = false;
5330 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005332 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005333 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005334 if (!first) pw.print(", ");
5335 first = false;
5336 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005337 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005338 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005339 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5340 if (!first) pw.print(", ");
5341 first = false;
5342 pw.print("anyDensity");
5343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005345 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005346 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5347 pw.print(" signatures="); pw.println(ps.signatures);
5348 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5349 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5350 pw.print(" installStatus="); pw.print(ps.installStatus);
5351 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 if (ps.disabledComponents.size() > 0) {
5353 pw.println(" disabledComponents:");
5354 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005355 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005356 }
5357 }
5358 if (ps.enabledComponents.size() > 0) {
5359 pw.println(" enabledComponents:");
5360 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005361 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005362 }
5363 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005364 if (ps.grantedPermissions.size() > 0) {
5365 pw.println(" grantedPermissions:");
5366 for (String s : ps.grantedPermissions) {
5367 pw.print(" "); pw.println(s);
5368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005370 if (ps.loadedPermissions.size() > 0) {
5371 pw.println(" loadedPermissions:");
5372 for (String s : ps.loadedPermissions) {
5373 pw.print(" "); pw.println(s);
5374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 }
5376 }
5377 }
5378 pw.println(" ");
5379 pw.println("Shared Users:");
5380 {
5381 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005382 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5383 pw.print(Integer.toHexString(System.identityHashCode(su)));
5384 pw.println("):");
5385 pw.print(" userId="); pw.print(su.userId);
5386 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 pw.println(" grantedPermissions:");
5388 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005389 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 }
5391 pw.println(" loadedPermissions:");
5392 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005393 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 }
5395 }
5396 }
5397 pw.println(" ");
5398 pw.println("Settings parse messages:");
5399 pw.println(mSettings.mReadMessages.toString());
5400 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005401
5402 synchronized (mProviders) {
5403 pw.println(" ");
5404 pw.println("Registered ContentProviders:");
5405 for (PackageParser.Provider p : mProviders.values()) {
5406 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5407 pw.println(p.toString());
5408 }
5409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 }
5411
5412 static final class BasePermission {
5413 final static int TYPE_NORMAL = 0;
5414 final static int TYPE_BUILTIN = 1;
5415 final static int TYPE_DYNAMIC = 2;
5416
5417 final String name;
5418 final String sourcePackage;
5419 final int type;
5420 PackageParser.Permission perm;
5421 PermissionInfo pendingInfo;
5422 int uid;
5423 int[] gids;
5424
5425 BasePermission(String _name, String _sourcePackage, int _type) {
5426 name = _name;
5427 sourcePackage = _sourcePackage;
5428 type = _type;
5429 }
5430 }
5431
5432 static class PackageSignatures {
5433 private Signature[] mSignatures;
5434
5435 PackageSignatures(Signature[] sigs) {
5436 assignSignatures(sigs);
5437 }
5438
5439 PackageSignatures() {
5440 }
5441
5442 void writeXml(XmlSerializer serializer, String tagName,
5443 ArrayList<Signature> pastSignatures) throws IOException {
5444 if (mSignatures == null) {
5445 return;
5446 }
5447 serializer.startTag(null, tagName);
5448 serializer.attribute(null, "count",
5449 Integer.toString(mSignatures.length));
5450 for (int i=0; i<mSignatures.length; i++) {
5451 serializer.startTag(null, "cert");
5452 final Signature sig = mSignatures[i];
5453 final int sigHash = sig.hashCode();
5454 final int numPast = pastSignatures.size();
5455 int j;
5456 for (j=0; j<numPast; j++) {
5457 Signature pastSig = pastSignatures.get(j);
5458 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5459 serializer.attribute(null, "index", Integer.toString(j));
5460 break;
5461 }
5462 }
5463 if (j >= numPast) {
5464 pastSignatures.add(sig);
5465 serializer.attribute(null, "index", Integer.toString(numPast));
5466 serializer.attribute(null, "key", sig.toCharsString());
5467 }
5468 serializer.endTag(null, "cert");
5469 }
5470 serializer.endTag(null, tagName);
5471 }
5472
5473 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5474 throws IOException, XmlPullParserException {
5475 String countStr = parser.getAttributeValue(null, "count");
5476 if (countStr == null) {
5477 reportSettingsProblem(Log.WARN,
5478 "Error in package manager settings: <signatures> has"
5479 + " no count at " + parser.getPositionDescription());
5480 XmlUtils.skipCurrentTag(parser);
5481 }
5482 final int count = Integer.parseInt(countStr);
5483 mSignatures = new Signature[count];
5484 int pos = 0;
5485
5486 int outerDepth = parser.getDepth();
5487 int type;
5488 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5489 && (type != XmlPullParser.END_TAG
5490 || parser.getDepth() > outerDepth)) {
5491 if (type == XmlPullParser.END_TAG
5492 || type == XmlPullParser.TEXT) {
5493 continue;
5494 }
5495
5496 String tagName = parser.getName();
5497 if (tagName.equals("cert")) {
5498 if (pos < count) {
5499 String index = parser.getAttributeValue(null, "index");
5500 if (index != null) {
5501 try {
5502 int idx = Integer.parseInt(index);
5503 String key = parser.getAttributeValue(null, "key");
5504 if (key == null) {
5505 if (idx >= 0 && idx < pastSignatures.size()) {
5506 Signature sig = pastSignatures.get(idx);
5507 if (sig != null) {
5508 mSignatures[pos] = pastSignatures.get(idx);
5509 pos++;
5510 } else {
5511 reportSettingsProblem(Log.WARN,
5512 "Error in package manager settings: <cert> "
5513 + "index " + index + " is not defined at "
5514 + parser.getPositionDescription());
5515 }
5516 } else {
5517 reportSettingsProblem(Log.WARN,
5518 "Error in package manager settings: <cert> "
5519 + "index " + index + " is out of bounds at "
5520 + parser.getPositionDescription());
5521 }
5522 } else {
5523 while (pastSignatures.size() <= idx) {
5524 pastSignatures.add(null);
5525 }
5526 Signature sig = new Signature(key);
5527 pastSignatures.set(idx, sig);
5528 mSignatures[pos] = sig;
5529 pos++;
5530 }
5531 } catch (NumberFormatException e) {
5532 reportSettingsProblem(Log.WARN,
5533 "Error in package manager settings: <cert> "
5534 + "index " + index + " is not a number at "
5535 + parser.getPositionDescription());
5536 }
5537 } else {
5538 reportSettingsProblem(Log.WARN,
5539 "Error in package manager settings: <cert> has"
5540 + " no index at " + parser.getPositionDescription());
5541 }
5542 } else {
5543 reportSettingsProblem(Log.WARN,
5544 "Error in package manager settings: too "
5545 + "many <cert> tags, expected " + count
5546 + " at " + parser.getPositionDescription());
5547 }
5548 } else {
5549 reportSettingsProblem(Log.WARN,
5550 "Unknown element under <cert>: "
5551 + parser.getName());
5552 }
5553 XmlUtils.skipCurrentTag(parser);
5554 }
5555
5556 if (pos < count) {
5557 // Should never happen -- there is an error in the written
5558 // settings -- but if it does we don't want to generate
5559 // a bad array.
5560 Signature[] newSigs = new Signature[pos];
5561 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5562 mSignatures = newSigs;
5563 }
5564 }
5565
5566 /**
5567 * If any of the given 'sigs' is contained in the existing signatures,
5568 * then completely replace the current signatures with the ones in
5569 * 'sigs'. This is used for updating an existing package to a newly
5570 * installed version.
5571 */
5572 boolean updateSignatures(Signature[] sigs, boolean update) {
5573 if (mSignatures == null) {
5574 if (update) {
5575 assignSignatures(sigs);
5576 }
5577 return true;
5578 }
5579 if (sigs == null) {
5580 return false;
5581 }
5582
5583 for (int i=0; i<sigs.length; i++) {
5584 Signature sig = sigs[i];
5585 for (int j=0; j<mSignatures.length; j++) {
5586 if (mSignatures[j].equals(sig)) {
5587 if (update) {
5588 assignSignatures(sigs);
5589 }
5590 return true;
5591 }
5592 }
5593 }
5594 return false;
5595 }
5596
5597 /**
5598 * If any of the given 'sigs' is contained in the existing signatures,
5599 * then add in any new signatures found in 'sigs'. This is used for
5600 * including a new package into an existing shared user id.
5601 */
5602 boolean mergeSignatures(Signature[] sigs, boolean update) {
5603 if (mSignatures == null) {
5604 if (update) {
5605 assignSignatures(sigs);
5606 }
5607 return true;
5608 }
5609 if (sigs == null) {
5610 return false;
5611 }
5612
5613 Signature[] added = null;
5614 int addedCount = 0;
5615 boolean haveMatch = false;
5616 for (int i=0; i<sigs.length; i++) {
5617 Signature sig = sigs[i];
5618 boolean found = false;
5619 for (int j=0; j<mSignatures.length; j++) {
5620 if (mSignatures[j].equals(sig)) {
5621 found = true;
5622 haveMatch = true;
5623 break;
5624 }
5625 }
5626
5627 if (!found) {
5628 if (added == null) {
5629 added = new Signature[sigs.length];
5630 }
5631 added[i] = sig;
5632 addedCount++;
5633 }
5634 }
5635
5636 if (!haveMatch) {
5637 // Nothing matched -- reject the new signatures.
5638 return false;
5639 }
5640 if (added == null) {
5641 // Completely matched -- nothing else to do.
5642 return true;
5643 }
5644
5645 // Add additional signatures in.
5646 if (update) {
5647 Signature[] total = new Signature[addedCount+mSignatures.length];
5648 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5649 int j = mSignatures.length;
5650 for (int i=0; i<added.length; i++) {
5651 if (added[i] != null) {
5652 total[j] = added[i];
5653 j++;
5654 }
5655 }
5656 mSignatures = total;
5657 }
5658 return true;
5659 }
5660
5661 private void assignSignatures(Signature[] sigs) {
5662 if (sigs == null) {
5663 mSignatures = null;
5664 return;
5665 }
5666 mSignatures = new Signature[sigs.length];
5667 for (int i=0; i<sigs.length; i++) {
5668 mSignatures[i] = sigs[i];
5669 }
5670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005672 @Override
5673 public String toString() {
5674 StringBuffer buf = new StringBuffer(128);
5675 buf.append("PackageSignatures{");
5676 buf.append(Integer.toHexString(System.identityHashCode(this)));
5677 buf.append(" [");
5678 if (mSignatures != null) {
5679 for (int i=0; i<mSignatures.length; i++) {
5680 if (i > 0) buf.append(", ");
5681 buf.append(Integer.toHexString(
5682 System.identityHashCode(mSignatures[i])));
5683 }
5684 }
5685 buf.append("]}");
5686 return buf.toString();
5687 }
5688 }
5689
5690 static class PreferredActivity extends IntentFilter {
5691 final int mMatch;
5692 final String[] mSetPackages;
5693 final String[] mSetClasses;
5694 final String[] mSetComponents;
5695 final ComponentName mActivity;
5696 final String mShortActivity;
5697 String mParseError;
5698
5699 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5700 ComponentName activity) {
5701 super(filter);
5702 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5703 mActivity = activity;
5704 mShortActivity = activity.flattenToShortString();
5705 mParseError = null;
5706 if (set != null) {
5707 final int N = set.length;
5708 String[] myPackages = new String[N];
5709 String[] myClasses = new String[N];
5710 String[] myComponents = new String[N];
5711 for (int i=0; i<N; i++) {
5712 ComponentName cn = set[i];
5713 if (cn == null) {
5714 mSetPackages = null;
5715 mSetClasses = null;
5716 mSetComponents = null;
5717 return;
5718 }
5719 myPackages[i] = cn.getPackageName().intern();
5720 myClasses[i] = cn.getClassName().intern();
5721 myComponents[i] = cn.flattenToShortString().intern();
5722 }
5723 mSetPackages = myPackages;
5724 mSetClasses = myClasses;
5725 mSetComponents = myComponents;
5726 } else {
5727 mSetPackages = null;
5728 mSetClasses = null;
5729 mSetComponents = null;
5730 }
5731 }
5732
5733 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5734 IOException {
5735 mShortActivity = parser.getAttributeValue(null, "name");
5736 mActivity = ComponentName.unflattenFromString(mShortActivity);
5737 if (mActivity == null) {
5738 mParseError = "Bad activity name " + mShortActivity;
5739 }
5740 String matchStr = parser.getAttributeValue(null, "match");
5741 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5742 String setCountStr = parser.getAttributeValue(null, "set");
5743 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5744
5745 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5746 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5747 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5748
5749 int setPos = 0;
5750
5751 int outerDepth = parser.getDepth();
5752 int type;
5753 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5754 && (type != XmlPullParser.END_TAG
5755 || parser.getDepth() > outerDepth)) {
5756 if (type == XmlPullParser.END_TAG
5757 || type == XmlPullParser.TEXT) {
5758 continue;
5759 }
5760
5761 String tagName = parser.getName();
5762 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5763 // + parser.getDepth() + " tag=" + tagName);
5764 if (tagName.equals("set")) {
5765 String name = parser.getAttributeValue(null, "name");
5766 if (name == null) {
5767 if (mParseError == null) {
5768 mParseError = "No name in set tag in preferred activity "
5769 + mShortActivity;
5770 }
5771 } else if (setPos >= setCount) {
5772 if (mParseError == null) {
5773 mParseError = "Too many set tags in preferred activity "
5774 + mShortActivity;
5775 }
5776 } else {
5777 ComponentName cn = ComponentName.unflattenFromString(name);
5778 if (cn == null) {
5779 if (mParseError == null) {
5780 mParseError = "Bad set name " + name + " in preferred activity "
5781 + mShortActivity;
5782 }
5783 } else {
5784 myPackages[setPos] = cn.getPackageName();
5785 myClasses[setPos] = cn.getClassName();
5786 myComponents[setPos] = name;
5787 setPos++;
5788 }
5789 }
5790 XmlUtils.skipCurrentTag(parser);
5791 } else if (tagName.equals("filter")) {
5792 //Log.i(TAG, "Starting to parse filter...");
5793 readFromXml(parser);
5794 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5795 // + parser.getDepth() + " tag=" + parser.getName());
5796 } else {
5797 reportSettingsProblem(Log.WARN,
5798 "Unknown element under <preferred-activities>: "
5799 + parser.getName());
5800 XmlUtils.skipCurrentTag(parser);
5801 }
5802 }
5803
5804 if (setPos != setCount) {
5805 if (mParseError == null) {
5806 mParseError = "Not enough set tags (expected " + setCount
5807 + " but found " + setPos + ") in " + mShortActivity;
5808 }
5809 }
5810
5811 mSetPackages = myPackages;
5812 mSetClasses = myClasses;
5813 mSetComponents = myComponents;
5814 }
5815
5816 public void writeToXml(XmlSerializer serializer) throws IOException {
5817 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5818 serializer.attribute(null, "name", mShortActivity);
5819 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5820 serializer.attribute(null, "set", Integer.toString(NS));
5821 for (int s=0; s<NS; s++) {
5822 serializer.startTag(null, "set");
5823 serializer.attribute(null, "name", mSetComponents[s]);
5824 serializer.endTag(null, "set");
5825 }
5826 serializer.startTag(null, "filter");
5827 super.writeToXml(serializer);
5828 serializer.endTag(null, "filter");
5829 }
5830
5831 boolean sameSet(List<ResolveInfo> query, int priority) {
5832 if (mSetPackages == null) return false;
5833 final int NQ = query.size();
5834 final int NS = mSetPackages.length;
5835 int numMatch = 0;
5836 for (int i=0; i<NQ; i++) {
5837 ResolveInfo ri = query.get(i);
5838 if (ri.priority != priority) continue;
5839 ActivityInfo ai = ri.activityInfo;
5840 boolean good = false;
5841 for (int j=0; j<NS; j++) {
5842 if (mSetPackages[j].equals(ai.packageName)
5843 && mSetClasses[j].equals(ai.name)) {
5844 numMatch++;
5845 good = true;
5846 break;
5847 }
5848 }
5849 if (!good) return false;
5850 }
5851 return numMatch == NS;
5852 }
5853 }
5854
5855 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005856 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 HashSet<String> grantedPermissions = new HashSet<String>();
5859 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005861 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 GrantedPermissions(int pkgFlags) {
5864 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5865 }
5866 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005868 /**
5869 * Settings base class for pending and resolved classes.
5870 */
5871 static class PackageSettingBase extends GrantedPermissions {
5872 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005873 File codePath;
5874 String codePathString;
5875 File resourcePath;
5876 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 private long timeStamp;
5878 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005879 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005880
5881 PackageSignatures signatures = new PackageSignatures();
5882
5883 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005885 /* Explicitly disabled components */
5886 HashSet<String> disabledComponents = new HashSet<String>(0);
5887 /* Explicitly enabled components */
5888 HashSet<String> enabledComponents = new HashSet<String>(0);
5889 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5890 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005891
Jacek Surazski65e13172009-04-28 15:26:38 +02005892 /* package name of the app that installed this package */
5893 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894
5895 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005896 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 super(pkgFlags);
5898 this.name = name;
5899 this.codePath = codePath;
5900 this.codePathString = codePath.toString();
5901 this.resourcePath = resourcePath;
5902 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005903 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005904 }
5905
Jacek Surazski65e13172009-04-28 15:26:38 +02005906 public void setInstallerPackageName(String packageName) {
5907 installerPackageName = packageName;
5908 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005909
Jacek Surazski65e13172009-04-28 15:26:38 +02005910 String getInstallerPackageName() {
5911 return installerPackageName;
5912 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 public void setInstallStatus(int newStatus) {
5915 installStatus = newStatus;
5916 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 public int getInstallStatus() {
5919 return installStatus;
5920 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 public void setTimeStamp(long newStamp) {
5923 if (newStamp != timeStamp) {
5924 timeStamp = newStamp;
5925 timeStampString = Long.toString(newStamp);
5926 }
5927 }
5928
5929 public void setTimeStamp(long newStamp, String newStampStr) {
5930 timeStamp = newStamp;
5931 timeStampString = newStampStr;
5932 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 public long getTimeStamp() {
5935 return timeStamp;
5936 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005938 public String getTimeStampStr() {
5939 return timeStampString;
5940 }
5941
5942 public void copyFrom(PackageSettingBase base) {
5943 grantedPermissions = base.grantedPermissions;
5944 gids = base.gids;
5945 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 timeStamp = base.timeStamp;
5948 timeStampString = base.timeStampString;
5949 signatures = base.signatures;
5950 permissionsFixed = base.permissionsFixed;
5951 disabledComponents = base.disabledComponents;
5952 enabledComponents = base.enabledComponents;
5953 enabled = base.enabled;
5954 installStatus = base.installStatus;
5955 }
5956
5957 void enableComponentLP(String componentClassName) {
5958 disabledComponents.remove(componentClassName);
5959 enabledComponents.add(componentClassName);
5960 }
5961
5962 void disableComponentLP(String componentClassName) {
5963 enabledComponents.remove(componentClassName);
5964 disabledComponents.add(componentClassName);
5965 }
5966
5967 void restoreComponentLP(String componentClassName) {
5968 enabledComponents.remove(componentClassName);
5969 disabledComponents.remove(componentClassName);
5970 }
5971
5972 int currentEnabledStateLP(String componentName) {
5973 if (enabledComponents.contains(componentName)) {
5974 return COMPONENT_ENABLED_STATE_ENABLED;
5975 } else if (disabledComponents.contains(componentName)) {
5976 return COMPONENT_ENABLED_STATE_DISABLED;
5977 } else {
5978 return COMPONENT_ENABLED_STATE_DEFAULT;
5979 }
5980 }
5981 }
5982
5983 /**
5984 * Settings data for a particular package we know about.
5985 */
5986 static final class PackageSetting extends PackageSettingBase {
5987 int userId;
5988 PackageParser.Package pkg;
5989 SharedUserSetting sharedUser;
5990
5991 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005992 int pVersionCode, int pkgFlags) {
5993 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005996 @Override
5997 public String toString() {
5998 return "PackageSetting{"
5999 + Integer.toHexString(System.identityHashCode(this))
6000 + " " + name + "/" + userId + "}";
6001 }
6002 }
6003
6004 /**
6005 * Settings data for a particular shared user ID we know about.
6006 */
6007 static final class SharedUserSetting extends GrantedPermissions {
6008 final String name;
6009 int userId;
6010 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6011 final PackageSignatures signatures = new PackageSignatures();
6012
6013 SharedUserSetting(String _name, int _pkgFlags) {
6014 super(_pkgFlags);
6015 name = _name;
6016 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 @Override
6019 public String toString() {
6020 return "SharedUserSetting{"
6021 + Integer.toHexString(System.identityHashCode(this))
6022 + " " + name + "/" + userId + "}";
6023 }
6024 }
6025
6026 /**
6027 * Holds information about dynamic settings.
6028 */
6029 private static final class Settings {
6030 private final File mSettingsFilename;
6031 private final File mBackupSettingsFilename;
6032 private final HashMap<String, PackageSetting> mPackages =
6033 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006034 // List of replaced system applications
6035 final HashMap<String, PackageSetting> mDisabledSysPackages =
6036 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038 // The user's preferred activities associated with particular intent
6039 // filters.
6040 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6041 new IntentResolver<PreferredActivity, PreferredActivity>() {
6042 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006043 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006044 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006045 out.print(prefix); out.print(
6046 Integer.toHexString(System.identityHashCode(filter)));
6047 out.print(' ');
6048 out.print(filter.mActivity.flattenToShortString());
6049 out.print(" match=0x");
6050 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006052 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006054 out.print(prefix); out.print(" ");
6055 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 }
6057 }
6058 }
6059 };
6060 private final HashMap<String, SharedUserSetting> mSharedUsers =
6061 new HashMap<String, SharedUserSetting>();
6062 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6063 private final SparseArray<Object> mOtherUserIds =
6064 new SparseArray<Object>();
6065
6066 // For reading/writing settings file.
6067 private final ArrayList<Signature> mPastSignatures =
6068 new ArrayList<Signature>();
6069
6070 // Mapping from permission names to info about them.
6071 final HashMap<String, BasePermission> mPermissions =
6072 new HashMap<String, BasePermission>();
6073
6074 // Mapping from permission tree names to info about them.
6075 final HashMap<String, BasePermission> mPermissionTrees =
6076 new HashMap<String, BasePermission>();
6077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 private final StringBuilder mReadMessages = new StringBuilder();
6079
6080 private static final class PendingPackage extends PackageSettingBase {
6081 final int sharedId;
6082
6083 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006084 int sharedId, int pVersionCode, int pkgFlags) {
6085 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 this.sharedId = sharedId;
6087 }
6088 }
6089 private final ArrayList<PendingPackage> mPendingPackages
6090 = new ArrayList<PendingPackage>();
6091
6092 Settings() {
6093 File dataDir = Environment.getDataDirectory();
6094 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006095 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6096 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006098 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 FileUtils.setPermissions(systemDir.toString(),
6100 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6101 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6102 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006103 FileUtils.setPermissions(systemSecureDir.toString(),
6104 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6105 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6106 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 mSettingsFilename = new File(systemDir, "packages.xml");
6108 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6109 }
6110
6111 PackageSetting getPackageLP(PackageParser.Package pkg,
6112 SharedUserSetting sharedUser, File codePath, File resourcePath,
6113 int pkgFlags, boolean create, boolean add) {
6114 final String name = pkg.packageName;
6115 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006116 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006117 return p;
6118 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006119
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006120 PackageSetting peekPackageLP(String name) {
6121 return mPackages.get(name);
6122 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006123 PackageSetting p = mPackages.get(name);
6124 if (p != null && p.codePath.getPath().equals(codePath)) {
6125 return p;
6126 }
6127 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006128 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006131 void setInstallStatus(String pkgName, int status) {
6132 PackageSetting p = mPackages.get(pkgName);
6133 if(p != null) {
6134 if(p.getInstallStatus() != status) {
6135 p.setInstallStatus(status);
6136 }
6137 }
6138 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006139
Jacek Surazski65e13172009-04-28 15:26:38 +02006140 void setInstallerPackageName(String pkgName,
6141 String installerPkgName) {
6142 PackageSetting p = mPackages.get(pkgName);
6143 if(p != null) {
6144 p.setInstallerPackageName(installerPkgName);
6145 }
6146 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006147
Jacek Surazski65e13172009-04-28 15:26:38 +02006148 String getInstallerPackageName(String pkgName) {
6149 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006150 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006151 }
6152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 int getInstallStatus(String pkgName) {
6154 PackageSetting p = mPackages.get(pkgName);
6155 if(p != null) {
6156 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 return -1;
6159 }
6160
6161 SharedUserSetting getSharedUserLP(String name,
6162 int pkgFlags, boolean create) {
6163 SharedUserSetting s = mSharedUsers.get(name);
6164 if (s == null) {
6165 if (!create) {
6166 return null;
6167 }
6168 s = new SharedUserSetting(name, pkgFlags);
6169 if (MULTIPLE_APPLICATION_UIDS) {
6170 s.userId = newUserIdLP(s);
6171 } else {
6172 s.userId = FIRST_APPLICATION_UID;
6173 }
6174 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6175 // < 0 means we couldn't assign a userid; fall out and return
6176 // s, which is currently null
6177 if (s.userId >= 0) {
6178 mSharedUsers.put(name, s);
6179 }
6180 }
6181
6182 return s;
6183 }
6184
6185 int disableSystemPackageLP(String name) {
6186 PackageSetting p = mPackages.get(name);
6187 if(p == null) {
6188 Log.w(TAG, "Package:"+name+" is not an installed package");
6189 return -1;
6190 }
6191 PackageSetting dp = mDisabledSysPackages.get(name);
6192 // always make sure the system package code and resource paths dont change
6193 if(dp == null) {
6194 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6195 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6196 }
6197 mDisabledSysPackages.put(name, p);
6198 }
6199 return removePackageLP(name);
6200 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 PackageSetting enableSystemPackageLP(String name) {
6203 PackageSetting p = mDisabledSysPackages.get(name);
6204 if(p == null) {
6205 Log.w(TAG, "Package:"+name+" is not disabled");
6206 return null;
6207 }
6208 // Reset flag in ApplicationInfo object
6209 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6210 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6211 }
6212 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006213 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214 mDisabledSysPackages.remove(name);
6215 return ret;
6216 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006219 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006220 PackageSetting p = mPackages.get(name);
6221 if (p != null) {
6222 if (p.userId == uid) {
6223 return p;
6224 }
6225 reportSettingsProblem(Log.ERROR,
6226 "Adding duplicate package, keeping first: " + name);
6227 return null;
6228 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006229 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006230 p.userId = uid;
6231 if (addUserIdLP(uid, p, name)) {
6232 mPackages.put(name, p);
6233 return p;
6234 }
6235 return null;
6236 }
6237
6238 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6239 SharedUserSetting s = mSharedUsers.get(name);
6240 if (s != null) {
6241 if (s.userId == uid) {
6242 return s;
6243 }
6244 reportSettingsProblem(Log.ERROR,
6245 "Adding duplicate shared user, keeping first: " + name);
6246 return null;
6247 }
6248 s = new SharedUserSetting(name, pkgFlags);
6249 s.userId = uid;
6250 if (addUserIdLP(uid, s, name)) {
6251 mSharedUsers.put(name, s);
6252 return s;
6253 }
6254 return null;
6255 }
6256
6257 private PackageSetting getPackageLP(String name,
6258 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006259 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 PackageSetting p = mPackages.get(name);
6261 if (p != null) {
6262 if (!p.codePath.equals(codePath)) {
6263 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006264 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006265 // This is an updated system app with versions in both system
6266 // and data partition. Just let the most recent version
6267 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006268 Log.w(TAG, "Trying to update system app code path from " +
6269 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006270 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006271 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006272 reportSettingsProblem(Log.WARN,
6273 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006274 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006276 }
6277 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 reportSettingsProblem(Log.WARN,
6279 "Package " + name + " shared user changed from "
6280 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6281 + " to "
6282 + (sharedUser != null ? sharedUser.name : "<nothing>")
6283 + "; replacing with new");
6284 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006285 } else {
6286 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6287 // If what we are scanning is a system package, then
6288 // make it so, regardless of whether it was previously
6289 // installed only in the data partition.
6290 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 }
6293 }
6294 if (p == null) {
6295 // Create a new PackageSettings entry. this can end up here because
6296 // of code path mismatch or user id mismatch of an updated system partition
6297 if (!create) {
6298 return null;
6299 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006300 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006302 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 if (sharedUser != null) {
6304 p.userId = sharedUser.userId;
6305 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006306 // Clone the setting here for disabled system packages
6307 PackageSetting dis = mDisabledSysPackages.get(name);
6308 if (dis != null) {
6309 // For disabled packages a new setting is created
6310 // from the existing user id. This still has to be
6311 // added to list of user id's
6312 // Copy signatures from previous setting
6313 if (dis.signatures.mSignatures != null) {
6314 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6315 }
6316 p.userId = dis.userId;
6317 // Clone permissions
6318 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6319 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6320 // Clone component info
6321 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6322 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6323 // Add new setting to list of user ids
6324 addUserIdLP(p.userId, p, name);
6325 } else {
6326 // Assign new user id
6327 p.userId = newUserIdLP(p);
6328 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 } else {
6330 p.userId = FIRST_APPLICATION_UID;
6331 }
6332 if (p.userId < 0) {
6333 reportSettingsProblem(Log.WARN,
6334 "Package " + name + " could not be assigned a valid uid");
6335 return null;
6336 }
6337 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006338 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006340 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 }
6342 }
6343 return p;
6344 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006345
6346 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6347 File codePath, File resourcePath) {
6348 p.pkg = pkg;
6349 // Update code path if needed
6350 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6351 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006352 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006353 p.codePath = codePath;
6354 p.codePathString = codePath.toString();
6355 }
6356 //Update resource path if needed
6357 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6358 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006359 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006360 p.resourcePath = resourcePath;
6361 p.resourcePathString = resourcePath.toString();
6362 }
6363 // Update version code if needed
6364 if (pkg.mVersionCode != p.versionCode) {
6365 p.versionCode = pkg.mVersionCode;
6366 }
6367 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6368 }
6369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 // Utility method that adds a PackageSetting to mPackages and
6371 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006372 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 SharedUserSetting sharedUser) {
6374 mPackages.put(name, p);
6375 if (sharedUser != null) {
6376 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6377 reportSettingsProblem(Log.ERROR,
6378 "Package " + p.name + " was user "
6379 + p.sharedUser + " but is now " + sharedUser
6380 + "; I am not changing its files so it will probably fail!");
6381 p.sharedUser.packages.remove(p);
6382 } else if (p.userId != sharedUser.userId) {
6383 reportSettingsProblem(Log.ERROR,
6384 "Package " + p.name + " was user id " + p.userId
6385 + " but is now user " + sharedUser
6386 + " with id " + sharedUser.userId
6387 + "; I am not changing its files so it will probably fail!");
6388 }
6389
6390 sharedUser.packages.add(p);
6391 p.sharedUser = sharedUser;
6392 p.userId = sharedUser.userId;
6393 }
6394 }
6395
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006396 /*
6397 * Update the shared user setting when a package using
6398 * specifying the shared user id is removed. The gids
6399 * associated with each permission of the deleted package
6400 * are removed from the shared user's gid list only if its
6401 * not in use by other permissions of packages in the
6402 * shared user setting.
6403 */
6404 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6406 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6407 return;
6408 }
6409 // No sharedUserId
6410 if (deletedPs.sharedUser == null) {
6411 return;
6412 }
6413 SharedUserSetting sus = deletedPs.sharedUser;
6414 // Update permissions
6415 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6416 boolean used = false;
6417 if (!sus.grantedPermissions.contains (eachPerm)) {
6418 continue;
6419 }
6420 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006421 if (pkg.pkg != null &&
6422 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6423 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 used = true;
6425 break;
6426 }
6427 }
6428 if (!used) {
6429 // can safely delete this permission from list
6430 sus.grantedPermissions.remove(eachPerm);
6431 sus.loadedPermissions.remove(eachPerm);
6432 }
6433 }
6434 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006435 int newGids[] = globalGids;
6436 for (String eachPerm : sus.grantedPermissions) {
6437 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006438 if (bp != null) {
6439 newGids = appendInts(newGids, bp.gids);
6440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 }
6442 sus.gids = newGids;
6443 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 private int removePackageLP(String name) {
6446 PackageSetting p = mPackages.get(name);
6447 if (p != null) {
6448 mPackages.remove(name);
6449 if (p.sharedUser != null) {
6450 p.sharedUser.packages.remove(p);
6451 if (p.sharedUser.packages.size() == 0) {
6452 mSharedUsers.remove(p.sharedUser.name);
6453 removeUserIdLP(p.sharedUser.userId);
6454 return p.sharedUser.userId;
6455 }
6456 } else {
6457 removeUserIdLP(p.userId);
6458 return p.userId;
6459 }
6460 }
6461 return -1;
6462 }
6463
6464 private boolean addUserIdLP(int uid, Object obj, Object name) {
6465 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6466 return false;
6467 }
6468
6469 if (uid >= FIRST_APPLICATION_UID) {
6470 int N = mUserIds.size();
6471 final int index = uid - FIRST_APPLICATION_UID;
6472 while (index >= N) {
6473 mUserIds.add(null);
6474 N++;
6475 }
6476 if (mUserIds.get(index) != null) {
6477 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006478 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 + " name=" + name);
6480 return false;
6481 }
6482 mUserIds.set(index, obj);
6483 } else {
6484 if (mOtherUserIds.get(uid) != null) {
6485 reportSettingsProblem(Log.ERROR,
6486 "Adding duplicate shared id: " + uid
6487 + " name=" + name);
6488 return false;
6489 }
6490 mOtherUserIds.put(uid, obj);
6491 }
6492 return true;
6493 }
6494
6495 public Object getUserIdLP(int uid) {
6496 if (uid >= FIRST_APPLICATION_UID) {
6497 int N = mUserIds.size();
6498 final int index = uid - FIRST_APPLICATION_UID;
6499 return index < N ? mUserIds.get(index) : null;
6500 } else {
6501 return mOtherUserIds.get(uid);
6502 }
6503 }
6504
6505 private void removeUserIdLP(int uid) {
6506 if (uid >= FIRST_APPLICATION_UID) {
6507 int N = mUserIds.size();
6508 final int index = uid - FIRST_APPLICATION_UID;
6509 if (index < N) mUserIds.set(index, null);
6510 } else {
6511 mOtherUserIds.remove(uid);
6512 }
6513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 void writeLP() {
6516 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6517
6518 // Keep the old settings around until we know the new ones have
6519 // been successfully written.
6520 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006521 // Presence of backup settings file indicates that we failed
6522 // to persist settings earlier. So preserve the older
6523 // backup for future reference since the current settings
6524 // might have been corrupted.
6525 if (!mBackupSettingsFilename.exists()) {
6526 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6527 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6528 return;
6529 }
6530 } else {
6531 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 }
6534
6535 mPastSignatures.clear();
6536
6537 try {
6538 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6539
6540 //XmlSerializer serializer = XmlUtils.serializerInstance();
6541 XmlSerializer serializer = new FastXmlSerializer();
6542 serializer.setOutput(str, "utf-8");
6543 serializer.startDocument(null, true);
6544 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6545
6546 serializer.startTag(null, "packages");
6547
6548 serializer.startTag(null, "permission-trees");
6549 for (BasePermission bp : mPermissionTrees.values()) {
6550 writePermission(serializer, bp);
6551 }
6552 serializer.endTag(null, "permission-trees");
6553
6554 serializer.startTag(null, "permissions");
6555 for (BasePermission bp : mPermissions.values()) {
6556 writePermission(serializer, bp);
6557 }
6558 serializer.endTag(null, "permissions");
6559
6560 for (PackageSetting pkg : mPackages.values()) {
6561 writePackage(serializer, pkg);
6562 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006564 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6565 writeDisabledSysPackage(serializer, pkg);
6566 }
6567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 serializer.startTag(null, "preferred-activities");
6569 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6570 serializer.startTag(null, "item");
6571 pa.writeToXml(serializer);
6572 serializer.endTag(null, "item");
6573 }
6574 serializer.endTag(null, "preferred-activities");
6575
6576 for (SharedUserSetting usr : mSharedUsers.values()) {
6577 serializer.startTag(null, "shared-user");
6578 serializer.attribute(null, "name", usr.name);
6579 serializer.attribute(null, "userId",
6580 Integer.toString(usr.userId));
6581 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6582 serializer.startTag(null, "perms");
6583 for (String name : usr.grantedPermissions) {
6584 serializer.startTag(null, "item");
6585 serializer.attribute(null, "name", name);
6586 serializer.endTag(null, "item");
6587 }
6588 serializer.endTag(null, "perms");
6589 serializer.endTag(null, "shared-user");
6590 }
6591
6592 serializer.endTag(null, "packages");
6593
6594 serializer.endDocument();
6595
6596 str.flush();
6597 str.close();
6598
6599 // New settings successfully written, old ones are no longer
6600 // needed.
6601 mBackupSettingsFilename.delete();
6602 FileUtils.setPermissions(mSettingsFilename.toString(),
6603 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6604 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6605 |FileUtils.S_IROTH,
6606 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006607 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608
6609 } catch(XmlPullParserException e) {
6610 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 -08006611 } catch(java.io.IOException e) {
6612 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006614 // Clean up partially written file
6615 if (mSettingsFilename.exists()) {
6616 if (!mSettingsFilename.delete()) {
6617 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6618 }
6619 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006620 //Debug.stopMethodTracing();
6621 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006622
6623 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 throws java.io.IOException {
6625 serializer.startTag(null, "updated-package");
6626 serializer.attribute(null, "name", pkg.name);
6627 serializer.attribute(null, "codePath", pkg.codePathString);
6628 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006629 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6631 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6632 }
6633 if (pkg.sharedUser == null) {
6634 serializer.attribute(null, "userId",
6635 Integer.toString(pkg.userId));
6636 } else {
6637 serializer.attribute(null, "sharedUserId",
6638 Integer.toString(pkg.userId));
6639 }
6640 serializer.startTag(null, "perms");
6641 if (pkg.sharedUser == null) {
6642 // If this is a shared user, the permissions will
6643 // be written there. We still need to write an
6644 // empty permissions list so permissionsFixed will
6645 // be set.
6646 for (final String name : pkg.grantedPermissions) {
6647 BasePermission bp = mPermissions.get(name);
6648 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6649 // We only need to write signature or system permissions but this wont
6650 // match the semantics of grantedPermissions. So write all permissions.
6651 serializer.startTag(null, "item");
6652 serializer.attribute(null, "name", name);
6653 serializer.endTag(null, "item");
6654 }
6655 }
6656 }
6657 serializer.endTag(null, "perms");
6658 serializer.endTag(null, "updated-package");
6659 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006660
6661 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006662 throws java.io.IOException {
6663 serializer.startTag(null, "package");
6664 serializer.attribute(null, "name", pkg.name);
6665 serializer.attribute(null, "codePath", pkg.codePathString);
6666 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6667 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6668 }
6669 serializer.attribute(null, "system",
6670 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6671 ? "true" : "false");
6672 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006673 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 if (pkg.sharedUser == null) {
6675 serializer.attribute(null, "userId",
6676 Integer.toString(pkg.userId));
6677 } else {
6678 serializer.attribute(null, "sharedUserId",
6679 Integer.toString(pkg.userId));
6680 }
6681 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6682 serializer.attribute(null, "enabled",
6683 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6684 ? "true" : "false");
6685 }
6686 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6687 serializer.attribute(null, "installStatus", "false");
6688 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006689 if (pkg.installerPackageName != null) {
6690 serializer.attribute(null, "installer", pkg.installerPackageName);
6691 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6693 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6694 serializer.startTag(null, "perms");
6695 if (pkg.sharedUser == null) {
6696 // If this is a shared user, the permissions will
6697 // be written there. We still need to write an
6698 // empty permissions list so permissionsFixed will
6699 // be set.
6700 for (final String name : pkg.grantedPermissions) {
6701 serializer.startTag(null, "item");
6702 serializer.attribute(null, "name", name);
6703 serializer.endTag(null, "item");
6704 }
6705 }
6706 serializer.endTag(null, "perms");
6707 }
6708 if (pkg.disabledComponents.size() > 0) {
6709 serializer.startTag(null, "disabled-components");
6710 for (final String name : pkg.disabledComponents) {
6711 serializer.startTag(null, "item");
6712 serializer.attribute(null, "name", name);
6713 serializer.endTag(null, "item");
6714 }
6715 serializer.endTag(null, "disabled-components");
6716 }
6717 if (pkg.enabledComponents.size() > 0) {
6718 serializer.startTag(null, "enabled-components");
6719 for (final String name : pkg.enabledComponents) {
6720 serializer.startTag(null, "item");
6721 serializer.attribute(null, "name", name);
6722 serializer.endTag(null, "item");
6723 }
6724 serializer.endTag(null, "enabled-components");
6725 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006727 serializer.endTag(null, "package");
6728 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 void writePermission(XmlSerializer serializer, BasePermission bp)
6731 throws XmlPullParserException, java.io.IOException {
6732 if (bp.type != BasePermission.TYPE_BUILTIN
6733 && bp.sourcePackage != null) {
6734 serializer.startTag(null, "item");
6735 serializer.attribute(null, "name", bp.name);
6736 serializer.attribute(null, "package", bp.sourcePackage);
6737 if (DEBUG_SETTINGS) Log.v(TAG,
6738 "Writing perm: name=" + bp.name + " type=" + bp.type);
6739 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6740 PermissionInfo pi = bp.perm != null ? bp.perm.info
6741 : bp.pendingInfo;
6742 if (pi != null) {
6743 serializer.attribute(null, "type", "dynamic");
6744 if (pi.icon != 0) {
6745 serializer.attribute(null, "icon",
6746 Integer.toString(pi.icon));
6747 }
6748 if (pi.nonLocalizedLabel != null) {
6749 serializer.attribute(null, "label",
6750 pi.nonLocalizedLabel.toString());
6751 }
6752 if (pi.protectionLevel !=
6753 PermissionInfo.PROTECTION_NORMAL) {
6754 serializer.attribute(null, "protection",
6755 Integer.toString(pi.protectionLevel));
6756 }
6757 }
6758 }
6759 serializer.endTag(null, "item");
6760 }
6761 }
6762
6763 String getReadMessagesLP() {
6764 return mReadMessages.toString();
6765 }
6766
Oscar Montemayora8529f62009-11-18 10:14:20 -08006767 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6769 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006770 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771 while(its.hasNext()) {
6772 String key = its.next();
6773 PackageSetting ps = mPackages.get(key);
6774 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08006775 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 }
6777 }
6778 return ret;
6779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006781 boolean readLP() {
6782 FileInputStream str = null;
6783 if (mBackupSettingsFilename.exists()) {
6784 try {
6785 str = new FileInputStream(mBackupSettingsFilename);
6786 mReadMessages.append("Reading from backup settings file\n");
6787 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006788 if (mSettingsFilename.exists()) {
6789 // If both the backup and settings file exist, we
6790 // ignore the settings since it might have been
6791 // corrupted.
6792 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6793 mSettingsFilename.delete();
6794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006795 } catch (java.io.IOException e) {
6796 // We'll try for the normal settings file.
6797 }
6798 }
6799
6800 mPastSignatures.clear();
6801
6802 try {
6803 if (str == null) {
6804 if (!mSettingsFilename.exists()) {
6805 mReadMessages.append("No settings file found\n");
6806 Log.i(TAG, "No current settings file!");
6807 return false;
6808 }
6809 str = new FileInputStream(mSettingsFilename);
6810 }
6811 XmlPullParser parser = Xml.newPullParser();
6812 parser.setInput(str, null);
6813
6814 int type;
6815 while ((type=parser.next()) != XmlPullParser.START_TAG
6816 && type != XmlPullParser.END_DOCUMENT) {
6817 ;
6818 }
6819
6820 if (type != XmlPullParser.START_TAG) {
6821 mReadMessages.append("No start tag found in settings file\n");
6822 Log.e(TAG, "No start tag found in package manager settings");
6823 return false;
6824 }
6825
6826 int outerDepth = parser.getDepth();
6827 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6828 && (type != XmlPullParser.END_TAG
6829 || parser.getDepth() > outerDepth)) {
6830 if (type == XmlPullParser.END_TAG
6831 || type == XmlPullParser.TEXT) {
6832 continue;
6833 }
6834
6835 String tagName = parser.getName();
6836 if (tagName.equals("package")) {
6837 readPackageLP(parser);
6838 } else if (tagName.equals("permissions")) {
6839 readPermissionsLP(mPermissions, parser);
6840 } else if (tagName.equals("permission-trees")) {
6841 readPermissionsLP(mPermissionTrees, parser);
6842 } else if (tagName.equals("shared-user")) {
6843 readSharedUserLP(parser);
6844 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006845 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006846 } else if (tagName.equals("preferred-activities")) {
6847 readPreferredActivitiesLP(parser);
6848 } else if(tagName.equals("updated-package")) {
6849 readDisabledSysPackageLP(parser);
6850 } else {
6851 Log.w(TAG, "Unknown element under <packages>: "
6852 + parser.getName());
6853 XmlUtils.skipCurrentTag(parser);
6854 }
6855 }
6856
6857 str.close();
6858
6859 } catch(XmlPullParserException e) {
6860 mReadMessages.append("Error reading: " + e.toString());
6861 Log.e(TAG, "Error reading package manager settings", e);
6862
6863 } catch(java.io.IOException e) {
6864 mReadMessages.append("Error reading: " + e.toString());
6865 Log.e(TAG, "Error reading package manager settings", e);
6866
6867 }
6868
6869 int N = mPendingPackages.size();
6870 for (int i=0; i<N; i++) {
6871 final PendingPackage pp = mPendingPackages.get(i);
6872 Object idObj = getUserIdLP(pp.sharedId);
6873 if (idObj != null && idObj instanceof SharedUserSetting) {
6874 PackageSetting p = getPackageLP(pp.name,
6875 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006876 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006877 if (p == null) {
6878 Log.w(TAG, "Unable to create application package for "
6879 + pp.name);
6880 continue;
6881 }
6882 p.copyFrom(pp);
6883 } else if (idObj != null) {
6884 String msg = "Bad package setting: package " + pp.name
6885 + " has shared uid " + pp.sharedId
6886 + " that is not a shared uid\n";
6887 mReadMessages.append(msg);
6888 Log.e(TAG, msg);
6889 } else {
6890 String msg = "Bad package setting: package " + pp.name
6891 + " has shared uid " + pp.sharedId
6892 + " that is not defined\n";
6893 mReadMessages.append(msg);
6894 Log.e(TAG, msg);
6895 }
6896 }
6897 mPendingPackages.clear();
6898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006899 mReadMessages.append("Read completed successfully: "
6900 + mPackages.size() + " packages, "
6901 + mSharedUsers.size() + " shared uids\n");
6902
6903 return true;
6904 }
6905
6906 private int readInt(XmlPullParser parser, String ns, String name,
6907 int defValue) {
6908 String v = parser.getAttributeValue(ns, name);
6909 try {
6910 if (v == null) {
6911 return defValue;
6912 }
6913 return Integer.parseInt(v);
6914 } catch (NumberFormatException e) {
6915 reportSettingsProblem(Log.WARN,
6916 "Error in package manager settings: attribute " +
6917 name + " has bad integer value " + v + " at "
6918 + parser.getPositionDescription());
6919 }
6920 return defValue;
6921 }
6922
6923 private void readPermissionsLP(HashMap<String, BasePermission> out,
6924 XmlPullParser parser)
6925 throws IOException, XmlPullParserException {
6926 int outerDepth = parser.getDepth();
6927 int type;
6928 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6929 && (type != XmlPullParser.END_TAG
6930 || parser.getDepth() > outerDepth)) {
6931 if (type == XmlPullParser.END_TAG
6932 || type == XmlPullParser.TEXT) {
6933 continue;
6934 }
6935
6936 String tagName = parser.getName();
6937 if (tagName.equals("item")) {
6938 String name = parser.getAttributeValue(null, "name");
6939 String sourcePackage = parser.getAttributeValue(null, "package");
6940 String ptype = parser.getAttributeValue(null, "type");
6941 if (name != null && sourcePackage != null) {
6942 boolean dynamic = "dynamic".equals(ptype);
6943 BasePermission bp = new BasePermission(name, sourcePackage,
6944 dynamic
6945 ? BasePermission.TYPE_DYNAMIC
6946 : BasePermission.TYPE_NORMAL);
6947 if (dynamic) {
6948 PermissionInfo pi = new PermissionInfo();
6949 pi.packageName = sourcePackage.intern();
6950 pi.name = name.intern();
6951 pi.icon = readInt(parser, null, "icon", 0);
6952 pi.nonLocalizedLabel = parser.getAttributeValue(
6953 null, "label");
6954 pi.protectionLevel = readInt(parser, null, "protection",
6955 PermissionInfo.PROTECTION_NORMAL);
6956 bp.pendingInfo = pi;
6957 }
6958 out.put(bp.name, bp);
6959 } else {
6960 reportSettingsProblem(Log.WARN,
6961 "Error in package manager settings: permissions has"
6962 + " no name at " + parser.getPositionDescription());
6963 }
6964 } else {
6965 reportSettingsProblem(Log.WARN,
6966 "Unknown element reading permissions: "
6967 + parser.getName() + " at "
6968 + parser.getPositionDescription());
6969 }
6970 XmlUtils.skipCurrentTag(parser);
6971 }
6972 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974 private void readDisabledSysPackageLP(XmlPullParser parser)
6975 throws XmlPullParserException, IOException {
6976 String name = parser.getAttributeValue(null, "name");
6977 String codePathStr = parser.getAttributeValue(null, "codePath");
6978 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6979 if(resourcePathStr == null) {
6980 resourcePathStr = codePathStr;
6981 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006982 String version = parser.getAttributeValue(null, "version");
6983 int versionCode = 0;
6984 if (version != null) {
6985 try {
6986 versionCode = Integer.parseInt(version);
6987 } catch (NumberFormatException e) {
6988 }
6989 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006991 int pkgFlags = 0;
6992 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006993 PackageSetting ps = new PackageSetting(name,
6994 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006995 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 String timeStampStr = parser.getAttributeValue(null, "ts");
6997 if (timeStampStr != null) {
6998 try {
6999 long timeStamp = Long.parseLong(timeStampStr);
7000 ps.setTimeStamp(timeStamp, timeStampStr);
7001 } catch (NumberFormatException e) {
7002 }
7003 }
7004 String idStr = parser.getAttributeValue(null, "userId");
7005 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7006 if(ps.userId <= 0) {
7007 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7008 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7009 }
7010 int outerDepth = parser.getDepth();
7011 int type;
7012 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7013 && (type != XmlPullParser.END_TAG
7014 || parser.getDepth() > outerDepth)) {
7015 if (type == XmlPullParser.END_TAG
7016 || type == XmlPullParser.TEXT) {
7017 continue;
7018 }
7019
7020 String tagName = parser.getName();
7021 if (tagName.equals("perms")) {
7022 readGrantedPermissionsLP(parser,
7023 ps.grantedPermissions);
7024 } else {
7025 reportSettingsProblem(Log.WARN,
7026 "Unknown element under <updated-package>: "
7027 + parser.getName());
7028 XmlUtils.skipCurrentTag(parser);
7029 }
7030 }
7031 mDisabledSysPackages.put(name, ps);
7032 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 private void readPackageLP(XmlPullParser parser)
7035 throws XmlPullParserException, IOException {
7036 String name = null;
7037 String idStr = null;
7038 String sharedIdStr = null;
7039 String codePathStr = null;
7040 String resourcePathStr = null;
7041 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007042 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 int pkgFlags = 0;
7044 String timeStampStr;
7045 long timeStamp = 0;
7046 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007047 String version = null;
7048 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 try {
7050 name = parser.getAttributeValue(null, "name");
7051 idStr = parser.getAttributeValue(null, "userId");
7052 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7053 codePathStr = parser.getAttributeValue(null, "codePath");
7054 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007055 version = parser.getAttributeValue(null, "version");
7056 if (version != null) {
7057 try {
7058 versionCode = Integer.parseInt(version);
7059 } catch (NumberFormatException e) {
7060 }
7061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007063 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007064 if (systemStr != null) {
7065 if ("true".equals(systemStr)) {
7066 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7067 }
7068 } else {
7069 // Old settings that don't specify system... just treat
7070 // them as system, good enough.
7071 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7072 }
7073 timeStampStr = parser.getAttributeValue(null, "ts");
7074 if (timeStampStr != null) {
7075 try {
7076 timeStamp = Long.parseLong(timeStampStr);
7077 } catch (NumberFormatException e) {
7078 }
7079 }
7080 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7081 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7082 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7083 if (resourcePathStr == null) {
7084 resourcePathStr = codePathStr;
7085 }
7086 if (name == null) {
7087 reportSettingsProblem(Log.WARN,
7088 "Error in package manager settings: <package> has no name at "
7089 + parser.getPositionDescription());
7090 } else if (codePathStr == null) {
7091 reportSettingsProblem(Log.WARN,
7092 "Error in package manager settings: <package> has no codePath at "
7093 + parser.getPositionDescription());
7094 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007095 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007096 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007097 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7098 + ": userId=" + userId + " pkg=" + packageSetting);
7099 if (packageSetting == null) {
7100 reportSettingsProblem(Log.ERROR,
7101 "Failure adding uid " + userId
7102 + " while parsing settings at "
7103 + parser.getPositionDescription());
7104 } else {
7105 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7106 }
7107 } else if (sharedIdStr != null) {
7108 userId = sharedIdStr != null
7109 ? Integer.parseInt(sharedIdStr) : 0;
7110 if (userId > 0) {
7111 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007112 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007113 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7114 mPendingPackages.add((PendingPackage) packageSetting);
7115 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7116 + ": sharedUserId=" + userId + " pkg="
7117 + packageSetting);
7118 } else {
7119 reportSettingsProblem(Log.WARN,
7120 "Error in package manager settings: package "
7121 + name + " has bad sharedId " + sharedIdStr
7122 + " at " + parser.getPositionDescription());
7123 }
7124 } else {
7125 reportSettingsProblem(Log.WARN,
7126 "Error in package manager settings: package "
7127 + name + " has bad userId " + idStr + " at "
7128 + parser.getPositionDescription());
7129 }
7130 } catch (NumberFormatException e) {
7131 reportSettingsProblem(Log.WARN,
7132 "Error in package manager settings: package "
7133 + name + " has bad userId " + idStr + " at "
7134 + parser.getPositionDescription());
7135 }
7136 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007137 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 final String enabledStr = parser.getAttributeValue(null, "enabled");
7139 if (enabledStr != null) {
7140 if (enabledStr.equalsIgnoreCase("true")) {
7141 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7142 } else if (enabledStr.equalsIgnoreCase("false")) {
7143 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7144 } else if (enabledStr.equalsIgnoreCase("default")) {
7145 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7146 } else {
7147 reportSettingsProblem(Log.WARN,
7148 "Error in package manager settings: package "
7149 + name + " has bad enabled value: " + idStr
7150 + " at " + parser.getPositionDescription());
7151 }
7152 } else {
7153 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7154 }
7155 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7156 if (installStatusStr != null) {
7157 if (installStatusStr.equalsIgnoreCase("false")) {
7158 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7159 } else {
7160 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7161 }
7162 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 int outerDepth = parser.getDepth();
7165 int type;
7166 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7167 && (type != XmlPullParser.END_TAG
7168 || parser.getDepth() > outerDepth)) {
7169 if (type == XmlPullParser.END_TAG
7170 || type == XmlPullParser.TEXT) {
7171 continue;
7172 }
7173
7174 String tagName = parser.getName();
7175 if (tagName.equals("disabled-components")) {
7176 readDisabledComponentsLP(packageSetting, parser);
7177 } else if (tagName.equals("enabled-components")) {
7178 readEnabledComponentsLP(packageSetting, parser);
7179 } else if (tagName.equals("sigs")) {
7180 packageSetting.signatures.readXml(parser, mPastSignatures);
7181 } else if (tagName.equals("perms")) {
7182 readGrantedPermissionsLP(parser,
7183 packageSetting.loadedPermissions);
7184 packageSetting.permissionsFixed = true;
7185 } else {
7186 reportSettingsProblem(Log.WARN,
7187 "Unknown element under <package>: "
7188 + parser.getName());
7189 XmlUtils.skipCurrentTag(parser);
7190 }
7191 }
7192 } else {
7193 XmlUtils.skipCurrentTag(parser);
7194 }
7195 }
7196
7197 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7198 XmlPullParser parser)
7199 throws IOException, XmlPullParserException {
7200 int outerDepth = parser.getDepth();
7201 int type;
7202 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7203 && (type != XmlPullParser.END_TAG
7204 || parser.getDepth() > outerDepth)) {
7205 if (type == XmlPullParser.END_TAG
7206 || type == XmlPullParser.TEXT) {
7207 continue;
7208 }
7209
7210 String tagName = parser.getName();
7211 if (tagName.equals("item")) {
7212 String name = parser.getAttributeValue(null, "name");
7213 if (name != null) {
7214 packageSetting.disabledComponents.add(name.intern());
7215 } else {
7216 reportSettingsProblem(Log.WARN,
7217 "Error in package manager settings: <disabled-components> has"
7218 + " no name at " + parser.getPositionDescription());
7219 }
7220 } else {
7221 reportSettingsProblem(Log.WARN,
7222 "Unknown element under <disabled-components>: "
7223 + parser.getName());
7224 }
7225 XmlUtils.skipCurrentTag(parser);
7226 }
7227 }
7228
7229 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7230 XmlPullParser parser)
7231 throws IOException, XmlPullParserException {
7232 int outerDepth = parser.getDepth();
7233 int type;
7234 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7235 && (type != XmlPullParser.END_TAG
7236 || parser.getDepth() > outerDepth)) {
7237 if (type == XmlPullParser.END_TAG
7238 || type == XmlPullParser.TEXT) {
7239 continue;
7240 }
7241
7242 String tagName = parser.getName();
7243 if (tagName.equals("item")) {
7244 String name = parser.getAttributeValue(null, "name");
7245 if (name != null) {
7246 packageSetting.enabledComponents.add(name.intern());
7247 } else {
7248 reportSettingsProblem(Log.WARN,
7249 "Error in package manager settings: <enabled-components> has"
7250 + " no name at " + parser.getPositionDescription());
7251 }
7252 } else {
7253 reportSettingsProblem(Log.WARN,
7254 "Unknown element under <enabled-components>: "
7255 + parser.getName());
7256 }
7257 XmlUtils.skipCurrentTag(parser);
7258 }
7259 }
7260
7261 private void readSharedUserLP(XmlPullParser parser)
7262 throws XmlPullParserException, IOException {
7263 String name = null;
7264 String idStr = null;
7265 int pkgFlags = 0;
7266 SharedUserSetting su = null;
7267 try {
7268 name = parser.getAttributeValue(null, "name");
7269 idStr = parser.getAttributeValue(null, "userId");
7270 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7271 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7272 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7273 }
7274 if (name == null) {
7275 reportSettingsProblem(Log.WARN,
7276 "Error in package manager settings: <shared-user> has no name at "
7277 + parser.getPositionDescription());
7278 } else if (userId == 0) {
7279 reportSettingsProblem(Log.WARN,
7280 "Error in package manager settings: shared-user "
7281 + name + " has bad userId " + idStr + " at "
7282 + parser.getPositionDescription());
7283 } else {
7284 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7285 reportSettingsProblem(Log.ERROR,
7286 "Occurred while parsing settings at "
7287 + parser.getPositionDescription());
7288 }
7289 }
7290 } catch (NumberFormatException e) {
7291 reportSettingsProblem(Log.WARN,
7292 "Error in package manager settings: package "
7293 + name + " has bad userId " + idStr + " at "
7294 + parser.getPositionDescription());
7295 };
7296
7297 if (su != null) {
7298 int outerDepth = parser.getDepth();
7299 int type;
7300 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7301 && (type != XmlPullParser.END_TAG
7302 || parser.getDepth() > outerDepth)) {
7303 if (type == XmlPullParser.END_TAG
7304 || type == XmlPullParser.TEXT) {
7305 continue;
7306 }
7307
7308 String tagName = parser.getName();
7309 if (tagName.equals("sigs")) {
7310 su.signatures.readXml(parser, mPastSignatures);
7311 } else if (tagName.equals("perms")) {
7312 readGrantedPermissionsLP(parser, su.loadedPermissions);
7313 } else {
7314 reportSettingsProblem(Log.WARN,
7315 "Unknown element under <shared-user>: "
7316 + parser.getName());
7317 XmlUtils.skipCurrentTag(parser);
7318 }
7319 }
7320
7321 } else {
7322 XmlUtils.skipCurrentTag(parser);
7323 }
7324 }
7325
7326 private void readGrantedPermissionsLP(XmlPullParser parser,
7327 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7328 int outerDepth = parser.getDepth();
7329 int type;
7330 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7331 && (type != XmlPullParser.END_TAG
7332 || parser.getDepth() > outerDepth)) {
7333 if (type == XmlPullParser.END_TAG
7334 || type == XmlPullParser.TEXT) {
7335 continue;
7336 }
7337
7338 String tagName = parser.getName();
7339 if (tagName.equals("item")) {
7340 String name = parser.getAttributeValue(null, "name");
7341 if (name != null) {
7342 outPerms.add(name.intern());
7343 } else {
7344 reportSettingsProblem(Log.WARN,
7345 "Error in package manager settings: <perms> has"
7346 + " no name at " + parser.getPositionDescription());
7347 }
7348 } else {
7349 reportSettingsProblem(Log.WARN,
7350 "Unknown element under <perms>: "
7351 + parser.getName());
7352 }
7353 XmlUtils.skipCurrentTag(parser);
7354 }
7355 }
7356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 private void readPreferredActivitiesLP(XmlPullParser parser)
7358 throws XmlPullParserException, IOException {
7359 int outerDepth = parser.getDepth();
7360 int type;
7361 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7362 && (type != XmlPullParser.END_TAG
7363 || parser.getDepth() > outerDepth)) {
7364 if (type == XmlPullParser.END_TAG
7365 || type == XmlPullParser.TEXT) {
7366 continue;
7367 }
7368
7369 String tagName = parser.getName();
7370 if (tagName.equals("item")) {
7371 PreferredActivity pa = new PreferredActivity(parser);
7372 if (pa.mParseError == null) {
7373 mPreferredActivities.addFilter(pa);
7374 } else {
7375 reportSettingsProblem(Log.WARN,
7376 "Error in package manager settings: <preferred-activity> "
7377 + pa.mParseError + " at "
7378 + parser.getPositionDescription());
7379 }
7380 } else {
7381 reportSettingsProblem(Log.WARN,
7382 "Unknown element under <preferred-activities>: "
7383 + parser.getName());
7384 XmlUtils.skipCurrentTag(parser);
7385 }
7386 }
7387 }
7388
7389 // Returns -1 if we could not find an available UserId to assign
7390 private int newUserIdLP(Object obj) {
7391 // Let's be stupidly inefficient for now...
7392 final int N = mUserIds.size();
7393 for (int i=0; i<N; i++) {
7394 if (mUserIds.get(i) == null) {
7395 mUserIds.set(i, obj);
7396 return FIRST_APPLICATION_UID + i;
7397 }
7398 }
7399
7400 // None left?
7401 if (N >= MAX_APPLICATION_UIDS) {
7402 return -1;
7403 }
7404
7405 mUserIds.add(obj);
7406 return FIRST_APPLICATION_UID + N;
7407 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 public PackageSetting getDisabledSystemPkg(String name) {
7410 synchronized(mPackages) {
7411 PackageSetting ps = mDisabledSysPackages.get(name);
7412 return ps;
7413 }
7414 }
7415
7416 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7417 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7418 if (Config.LOGV) {
7419 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7420 + " componentName = " + componentInfo.name);
7421 Log.v(TAG, "enabledComponents: "
7422 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7423 Log.v(TAG, "disabledComponents: "
7424 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7425 }
7426 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7427 || ((componentInfo.enabled
7428 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7429 || (componentInfo.applicationInfo.enabled
7430 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7431 && !packageSettings.disabledComponents.contains(componentInfo.name))
7432 || packageSettings.enabledComponents.contains(componentInfo.name));
7433 }
7434 }
7435}