blob: 3320a53b71c9a3b0b9308e1152a8f95a4c27575e [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;
20import com.android.internal.util.FastXmlSerializer;
21import com.android.internal.util.XmlUtils;
22
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
125 private static final int REMOVE_EVENTS =
126 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
127 private static final int ADD_EVENTS =
128 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
129
130 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
131
132 static final int SCAN_MONITOR = 1<<0;
133 static final int SCAN_NO_DEX = 1<<1;
134 static final int SCAN_FORCE_DEX = 1<<2;
135 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
136 static final int SCAN_FORWARD_LOCKED = 1<<4;
The Android Open Source Project10592532009-03-18 17:39:46 -0700137 static final int SCAN_NEW_INSTALL = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
139 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
140 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700141 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
Dianne Hackborn851a5412009-05-08 12:06:44 -0700143 final int mSdkVersion = Build.VERSION.SDK_INT;
144 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
145 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 final Context mContext;
148 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700149 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 final DisplayMetrics mMetrics;
151 final int mDefParseFlags;
152 final String[] mSeparateProcesses;
153
154 // This is where all application persistent data goes.
155 final File mAppDataDir;
156
157 // This is the object monitoring the framework dir.
158 final FileObserver mFrameworkInstallObserver;
159
160 // This is the object monitoring the system app dir.
161 final FileObserver mSystemInstallObserver;
162
163 // This is the object monitoring mAppInstallDir.
164 final FileObserver mAppInstallObserver;
165
166 // This is the object monitoring mDrmAppPrivateInstallDir.
167 final FileObserver mDrmAppInstallObserver;
168
169 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
170 // LOCK HELD. Can be called with mInstallLock held.
171 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 final File mFrameworkDir;
174 final File mSystemAppDir;
175 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700176 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177
178 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
179 // apps.
180 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 // Lock for state used when installing and doing other long running
185 // operations. Methods that must be called with this lock held have
186 // the prefix "LI".
187 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 // These are the directories in the 3rd party applications installed dir
190 // that we have currently loaded packages from. Keys are the application's
191 // installed zip file (absolute codePath), and values are Package.
192 final HashMap<String, PackageParser.Package> mAppDirs =
193 new HashMap<String, PackageParser.Package>();
194
195 // Information for the parser to write more useful error messages.
196 File mScanningPath;
197 int mLastScanError;
198
199 final int[] mOutPermissions = new int[3];
200
201 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // Keys are String (package name), values are Package. This also serves
204 // as the lock for the global state. Methods that must be called with
205 // this lock held have the prefix "LP".
206 final HashMap<String, PackageParser.Package> mPackages =
207 new HashMap<String, PackageParser.Package>();
208
209 final Settings mSettings;
210 boolean mRestoredSettings;
211 boolean mReportedUidError;
212
213 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
214 int[] mGlobalGids;
215
216 // These are the built-in uid -> permission mappings that were read from the
217 // etc/permissions.xml file.
218 final SparseArray<HashSet<String>> mSystemPermissions =
219 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 // These are the built-in shared libraries that were read from the
222 // etc/permissions.xml file.
223 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800224
Dianne Hackborn49237342009-08-27 20:08:01 -0700225 // Temporary for building the final shared libraries for an .apk.
226 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800227
Dianne Hackborn49237342009-08-27 20:08:01 -0700228 // These are the features this devices supports that were read from the
229 // etc/permissions.xml file.
230 final HashMap<String, FeatureInfo> mAvailableFeatures =
231 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 // All available activities, for your resolving pleasure.
234 final ActivityIntentResolver mActivities =
235 new ActivityIntentResolver();
236
237 // All available receivers, for your resolving pleasure.
238 final ActivityIntentResolver mReceivers =
239 new ActivityIntentResolver();
240
241 // All available services, for your resolving pleasure.
242 final ServiceIntentResolver mServices = new ServiceIntentResolver();
243
244 // Keys are String (provider class name), values are Provider.
245 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
246 new HashMap<ComponentName, PackageParser.Provider>();
247
248 // Mapping from provider base names (first directory in content URI codePath)
249 // to the provider information.
250 final HashMap<String, PackageParser.Provider> mProviders =
251 new HashMap<String, PackageParser.Provider>();
252
253 // Mapping from instrumentation class names to info about them.
254 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
255 new HashMap<ComponentName, PackageParser.Instrumentation>();
256
257 // Mapping from permission names to info about them.
258 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
259 new HashMap<String, PackageParser.PermissionGroup>();
260
Dianne Hackborn854060af2009-07-09 18:14:31 -0700261 // Broadcast actions that are only available to the system.
262 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 boolean mSystemReady;
265 boolean mSafeMode;
266 boolean mHasSystemUidErrors;
267
268 ApplicationInfo mAndroidApplication;
269 final ActivityInfo mResolveActivity = new ActivityInfo();
270 final ResolveInfo mResolveInfo = new ResolveInfo();
271 ComponentName mResolveComponentName;
272 PackageParser.Package mPlatformPackage;
273
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700274 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800275 final HashMap<String, ArrayList<String>> mPendingBroadcasts
276 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700277 static final int SEND_PENDING_BROADCAST = 1;
278 // Delay time in millisecs
279 static final int BROADCAST_DELAY = 10 * 1000;
280
281 class PackageHandler extends Handler {
282 PackageHandler(Looper looper) {
283 super(looper);
284 }
285 public void handleMessage(Message msg) {
286 switch (msg.what) {
287 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800288 String packages[];
289 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700290 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700291 int uids[];
292 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800293 if (mPendingBroadcasts == null) {
294 return;
295 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700296 size = mPendingBroadcasts.size();
297 if (size <= 0) {
298 // Nothing to be done. Just return
299 return;
300 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800301 packages = new String[size];
302 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700303 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800304 Iterator<HashMap.Entry<String, ArrayList<String>>>
305 it = mPendingBroadcasts.entrySet().iterator();
306 int i = 0;
307 while (it.hasNext() && i < size) {
308 HashMap.Entry<String, ArrayList<String>> ent = it.next();
309 packages[i] = ent.getKey();
310 components[i] = ent.getValue();
311 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700312 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800313 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700314 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800315 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700316 mPendingBroadcasts.clear();
317 }
318 // Send broadcasts
319 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800320 sendPackageChangedBroadcast(packages[i], true,
321 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700322 }
323 break;
324 }
325 }
326 }
327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 public static final IPackageManager main(Context context, boolean factoryTest) {
329 PackageManagerService m = new PackageManagerService(context, factoryTest);
330 ServiceManager.addService("package", m);
331 return m;
332 }
333
334 static String[] splitString(String str, char sep) {
335 int count = 1;
336 int i = 0;
337 while ((i=str.indexOf(sep, i)) >= 0) {
338 count++;
339 i++;
340 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 String[] res = new String[count];
343 i=0;
344 count = 0;
345 int lastI=0;
346 while ((i=str.indexOf(sep, i)) >= 0) {
347 res[count] = str.substring(lastI, i);
348 count++;
349 i++;
350 lastI = i;
351 }
352 res[count] = str.substring(lastI, str.length());
353 return res;
354 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800357 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 if (mSdkVersion <= 0) {
361 Log.w(TAG, "**** ro.build.version.sdk not set!");
362 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 mContext = context;
365 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700366 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 mMetrics = new DisplayMetrics();
368 mSettings = new Settings();
369 mSettings.addSharedUserLP("android.uid.system",
370 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
371 mSettings.addSharedUserLP("android.uid.phone",
372 MULTIPLE_APPLICATION_UIDS
373 ? RADIO_UID : FIRST_APPLICATION_UID,
374 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400375 mSettings.addSharedUserLP("android.uid.log",
376 MULTIPLE_APPLICATION_UIDS
377 ? LOG_UID : FIRST_APPLICATION_UID,
378 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379
380 String separateProcesses = SystemProperties.get("debug.separate_processes");
381 if (separateProcesses != null && separateProcesses.length() > 0) {
382 if ("*".equals(separateProcesses)) {
383 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
384 mSeparateProcesses = null;
385 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
386 } else {
387 mDefParseFlags = 0;
388 mSeparateProcesses = separateProcesses.split(",");
389 Log.w(TAG, "Running with debug.separate_processes: "
390 + separateProcesses);
391 }
392 } else {
393 mDefParseFlags = 0;
394 mSeparateProcesses = null;
395 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 Installer installer = new Installer();
398 // Little hacky thing to check if installd is here, to determine
399 // whether we are running on the simulator and thus need to take
400 // care of building the /data file structure ourself.
401 // (apparently the sim now has a working installer)
402 if (installer.ping() && Process.supportsProcesses()) {
403 mInstaller = installer;
404 } else {
405 mInstaller = null;
406 }
407
408 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
409 Display d = wm.getDefaultDisplay();
410 d.getMetrics(mMetrics);
411
412 synchronized (mInstallLock) {
413 synchronized (mPackages) {
414 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700415 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 File dataDir = Environment.getDataDirectory();
418 mAppDataDir = new File(dataDir, "data");
419 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
420
421 if (mInstaller == null) {
422 // Make sure these dirs exist, when we are running in
423 // the simulator.
424 // Make a wide-open directory for random misc stuff.
425 File miscDir = new File(dataDir, "misc");
426 miscDir.mkdirs();
427 mAppDataDir.mkdirs();
428 mDrmAppPrivateInstallDir.mkdirs();
429 }
430
431 readPermissions();
432
433 mRestoredSettings = mSettings.readLP();
434 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800435
436 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 int scanMode = SCAN_MONITOR;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700440 if (mNoDexOpt) {
441 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800442 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700443 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700448 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700451 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 /**
454 * Out of paranoia, ensure that everything in the boot class
455 * path has been dexed.
456 */
457 String bootClassPath = System.getProperty("java.boot.class.path");
458 if (bootClassPath != null) {
459 String[] paths = splitString(bootClassPath, ':');
460 for (int i=0; i<paths.length; i++) {
461 try {
462 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
463 libFiles.add(paths[i]);
464 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700465 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 }
467 } catch (FileNotFoundException e) {
468 Log.w(TAG, "Boot class path not found: " + paths[i]);
469 } catch (IOException e) {
470 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
471 }
472 }
473 } else {
474 Log.w(TAG, "No BOOTCLASSPATH found!");
475 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 /**
478 * Also ensure all external libraries have had dexopt run on them.
479 */
480 if (mSharedLibraries.size() > 0) {
481 Iterator<String> libs = mSharedLibraries.values().iterator();
482 while (libs.hasNext()) {
483 String lib = libs.next();
484 try {
485 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
486 libFiles.add(lib);
487 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700488 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 }
490 } catch (FileNotFoundException e) {
491 Log.w(TAG, "Library not found: " + lib);
492 } catch (IOException e) {
493 Log.w(TAG, "Exception reading library: " + lib, e);
494 }
495 }
496 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 // Gross hack for now: we know this file doesn't contain any
499 // code, so don't dexopt it to avoid the resulting log spew.
500 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 /**
503 * And there are a number of commands implemented in Java, which
504 * we currently need to do the dexopt on so that they can be
505 * run from a non-root shell.
506 */
507 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700508 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 for (int i=0; i<frameworkFiles.length; i++) {
510 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
511 String path = libPath.getPath();
512 // Skip the file if we alrady did it.
513 if (libFiles.contains(path)) {
514 continue;
515 }
516 // Skip the file if it is not a type we want to dexopt.
517 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
518 continue;
519 }
520 try {
521 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
522 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700523 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
525 } catch (FileNotFoundException e) {
526 Log.w(TAG, "Jar not found: " + path);
527 } catch (IOException e) {
528 Log.w(TAG, "Exception reading jar: " + path, e);
529 }
530 }
531 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800532
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700533 if (didDexOpt) {
534 // If we had to do a dexopt of one of the previous
535 // things, then something on the system has changed.
536 // Consider this significant, and wipe away all other
537 // existing dexopt files to ensure we don't leave any
538 // dangling around.
539 String[] files = mDalvikCacheDir.list();
540 if (files != null) {
541 for (int i=0; i<files.length; i++) {
542 String fn = files[i];
543 if (fn.startsWith("data@app@")
544 || fn.startsWith("data@app-private@")) {
545 Log.i(TAG, "Pruning dalvik file: " + fn);
546 (new File(mDalvikCacheDir, fn)).delete();
547 }
548 }
549 }
550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 mFrameworkInstallObserver = new AppDirObserver(
554 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
555 mFrameworkInstallObserver.startWatching();
556 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
557 scanMode | SCAN_NO_DEX);
558 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
559 mSystemInstallObserver = new AppDirObserver(
560 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
561 mSystemInstallObserver.startWatching();
562 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
563 mAppInstallDir = new File(dataDir, "app");
564 if (mInstaller == null) {
565 // Make sure these dirs exist, when we are running in
566 // the simulator.
567 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
568 }
569 //look for any incomplete package installations
570 ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
571 //clean up list
572 for(int i = 0; i < deletePkgsList.size(); i++) {
573 //clean up here
574 cleanupInstallFailedPackage(deletePkgsList.get(i));
575 }
576 //delete tmp files
577 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800578
579 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 SystemClock.uptimeMillis());
581 mAppInstallObserver = new AppDirObserver(
582 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
583 mAppInstallObserver.startWatching();
584 scanDirLI(mAppInstallDir, 0, scanMode);
585
586 mDrmAppInstallObserver = new AppDirObserver(
587 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
588 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -0700589 scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800591 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 SystemClock.uptimeMillis());
593 Log.i(TAG, "Time to scan packages: "
594 + ((SystemClock.uptimeMillis()-startTime)/1000f)
595 + " seconds");
596
597 updatePermissionsLP();
598
599 mSettings.writeLP();
600
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800601 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 // Now after opening every single application zip, make sure they
605 // are all flushed. Not really needed, but keeps things nice and
606 // tidy.
607 Runtime.getRuntime().gc();
608 } // synchronized (mPackages)
609 } // synchronized (mInstallLock)
610 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 @Override
613 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
614 throws RemoteException {
615 try {
616 return super.onTransact(code, data, reply, flags);
617 } catch (RuntimeException e) {
618 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
619 Log.e(TAG, "Package Manager Crash", e);
620 }
621 throw e;
622 }
623 }
624
625 void cleanupInstallFailedPackage(String packageName) {
626 if (mInstaller != null) {
627 int retCode = mInstaller.remove(packageName);
628 if (retCode < 0) {
629 Log.w(TAG, "Couldn't remove app data directory for package: "
630 + packageName + ", retcode=" + retCode);
631 }
632 } else {
633 //for emulator
634 PackageParser.Package pkg = mPackages.get(packageName);
635 File dataDir = new File(pkg.applicationInfo.dataDir);
636 dataDir.delete();
637 }
638 mSettings.removePackageLP(packageName);
639 }
640
641 void readPermissions() {
642 // Read permissions from .../etc/permission directory.
643 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
644 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
645 Log.w(TAG, "No directory " + libraryDir + ", skipping");
646 return;
647 }
648 if (!libraryDir.canRead()) {
649 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
650 return;
651 }
652
653 // Iterate over the files in the directory and scan .xml files
654 for (File f : libraryDir.listFiles()) {
655 // We'll read platform.xml last
656 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
657 continue;
658 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 if (!f.getPath().endsWith(".xml")) {
661 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
662 continue;
663 }
664 if (!f.canRead()) {
665 Log.w(TAG, "Permissions library file " + f + " cannot be read");
666 continue;
667 }
668
669 readPermissionsFromXml(f);
670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
673 final File permFile = new File(Environment.getRootDirectory(),
674 "etc/permissions/platform.xml");
675 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800676
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700677 StringBuilder sb = new StringBuilder(128);
678 sb.append("Libs:");
679 Iterator<String> it = mSharedLibraries.keySet().iterator();
680 while (it.hasNext()) {
681 sb.append(' ');
682 String name = it.next();
683 sb.append(name);
684 sb.append(':');
685 sb.append(mSharedLibraries.get(name));
686 }
687 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800688
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700689 sb.setLength(0);
690 sb.append("Features:");
691 it = mAvailableFeatures.keySet().iterator();
692 while (it.hasNext()) {
693 sb.append(' ');
694 sb.append(it.next());
695 }
696 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800698
699 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 FileReader permReader = null;
701 try {
702 permReader = new FileReader(permFile);
703 } catch (FileNotFoundException e) {
704 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
705 return;
706 }
707
708 try {
709 XmlPullParser parser = Xml.newPullParser();
710 parser.setInput(permReader);
711
712 XmlUtils.beginDocument(parser, "permissions");
713
714 while (true) {
715 XmlUtils.nextElement(parser);
716 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
717 break;
718 }
719
720 String name = parser.getName();
721 if ("group".equals(name)) {
722 String gidStr = parser.getAttributeValue(null, "gid");
723 if (gidStr != null) {
724 int gid = Integer.parseInt(gidStr);
725 mGlobalGids = appendInt(mGlobalGids, gid);
726 } else {
727 Log.w(TAG, "<group> without gid at "
728 + parser.getPositionDescription());
729 }
730
731 XmlUtils.skipCurrentTag(parser);
732 continue;
733 } else if ("permission".equals(name)) {
734 String perm = parser.getAttributeValue(null, "name");
735 if (perm == null) {
736 Log.w(TAG, "<permission> without name at "
737 + parser.getPositionDescription());
738 XmlUtils.skipCurrentTag(parser);
739 continue;
740 }
741 perm = perm.intern();
742 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 } else if ("assign-permission".equals(name)) {
745 String perm = parser.getAttributeValue(null, "name");
746 if (perm == null) {
747 Log.w(TAG, "<assign-permission> without name at "
748 + parser.getPositionDescription());
749 XmlUtils.skipCurrentTag(parser);
750 continue;
751 }
752 String uidStr = parser.getAttributeValue(null, "uid");
753 if (uidStr == null) {
754 Log.w(TAG, "<assign-permission> without uid at "
755 + parser.getPositionDescription());
756 XmlUtils.skipCurrentTag(parser);
757 continue;
758 }
759 int uid = Process.getUidForName(uidStr);
760 if (uid < 0) {
761 Log.w(TAG, "<assign-permission> with unknown uid \""
762 + uidStr + "\" at "
763 + parser.getPositionDescription());
764 XmlUtils.skipCurrentTag(parser);
765 continue;
766 }
767 perm = perm.intern();
768 HashSet<String> perms = mSystemPermissions.get(uid);
769 if (perms == null) {
770 perms = new HashSet<String>();
771 mSystemPermissions.put(uid, perms);
772 }
773 perms.add(perm);
774 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 } else if ("library".equals(name)) {
777 String lname = parser.getAttributeValue(null, "name");
778 String lfile = parser.getAttributeValue(null, "file");
779 if (lname == null) {
780 Log.w(TAG, "<library> without name at "
781 + parser.getPositionDescription());
782 } else if (lfile == null) {
783 Log.w(TAG, "<library> without file at "
784 + parser.getPositionDescription());
785 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700786 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700787 mSharedLibraries.put(lname, lfile);
788 }
789 XmlUtils.skipCurrentTag(parser);
790 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800791
Dianne Hackborn49237342009-08-27 20:08:01 -0700792 } else if ("feature".equals(name)) {
793 String fname = parser.getAttributeValue(null, "name");
794 if (fname == null) {
795 Log.w(TAG, "<feature> without name at "
796 + parser.getPositionDescription());
797 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700798 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700799 FeatureInfo fi = new FeatureInfo();
800 fi.name = fname;
801 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 }
803 XmlUtils.skipCurrentTag(parser);
804 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 } else {
807 XmlUtils.skipCurrentTag(parser);
808 continue;
809 }
810
811 }
812 } catch (XmlPullParserException e) {
813 Log.w(TAG, "Got execption parsing permissions.", e);
814 } catch (IOException e) {
815 Log.w(TAG, "Got execption parsing permissions.", e);
816 }
817 }
818
819 void readPermission(XmlPullParser parser, String name)
820 throws IOException, XmlPullParserException {
821
822 name = name.intern();
823
824 BasePermission bp = mSettings.mPermissions.get(name);
825 if (bp == null) {
826 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
827 mSettings.mPermissions.put(name, bp);
828 }
829 int outerDepth = parser.getDepth();
830 int type;
831 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
832 && (type != XmlPullParser.END_TAG
833 || parser.getDepth() > outerDepth)) {
834 if (type == XmlPullParser.END_TAG
835 || type == XmlPullParser.TEXT) {
836 continue;
837 }
838
839 String tagName = parser.getName();
840 if ("group".equals(tagName)) {
841 String gidStr = parser.getAttributeValue(null, "gid");
842 if (gidStr != null) {
843 int gid = Process.getGidForName(gidStr);
844 bp.gids = appendInt(bp.gids, gid);
845 } else {
846 Log.w(TAG, "<group> without gid at "
847 + parser.getPositionDescription());
848 }
849 }
850 XmlUtils.skipCurrentTag(parser);
851 }
852 }
853
854 static int[] appendInt(int[] cur, int val) {
855 if (cur == null) {
856 return new int[] { val };
857 }
858 final int N = cur.length;
859 for (int i=0; i<N; i++) {
860 if (cur[i] == val) {
861 return cur;
862 }
863 }
864 int[] ret = new int[N+1];
865 System.arraycopy(cur, 0, ret, 0, N);
866 ret[N] = val;
867 return ret;
868 }
869
870 static int[] appendInts(int[] cur, int[] add) {
871 if (add == null) return cur;
872 if (cur == null) return add;
873 final int N = add.length;
874 for (int i=0; i<N; i++) {
875 cur = appendInt(cur, add[i]);
876 }
877 return cur;
878 }
879
880 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700881 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
882 // The package has been uninstalled but has retained data and resources.
883 return PackageParser.generatePackageInfo(p, null, flags);
884 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 final PackageSetting ps = (PackageSetting)p.mExtras;
886 if (ps == null) {
887 return null;
888 }
889 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
890 return PackageParser.generatePackageInfo(p, gp.gids, flags);
891 }
892
893 public PackageInfo getPackageInfo(String packageName, int flags) {
894 synchronized (mPackages) {
895 PackageParser.Package p = mPackages.get(packageName);
896 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700897 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 + ": " + p);
899 if (p != null) {
900 return generatePackageInfo(p, flags);
901 }
902 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
903 return generatePackageInfoFromSettingsLP(packageName, flags);
904 }
905 }
906 return null;
907 }
908
909 public int getPackageUid(String packageName) {
910 synchronized (mPackages) {
911 PackageParser.Package p = mPackages.get(packageName);
912 if(p != null) {
913 return p.applicationInfo.uid;
914 }
915 PackageSetting ps = mSettings.mPackages.get(packageName);
916 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
917 return -1;
918 }
919 p = ps.pkg;
920 return p != null ? p.applicationInfo.uid : -1;
921 }
922 }
923
924 public int[] getPackageGids(String packageName) {
925 synchronized (mPackages) {
926 PackageParser.Package p = mPackages.get(packageName);
927 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -0700928 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 + ": " + p);
930 if (p != null) {
931 final PackageSetting ps = (PackageSetting)p.mExtras;
932 final SharedUserSetting suid = ps.sharedUser;
933 return suid != null ? suid.gids : ps.gids;
934 }
935 }
936 // stupid thing to indicate an error.
937 return new int[0];
938 }
939
940 public PermissionInfo getPermissionInfo(String name, int flags) {
941 synchronized (mPackages) {
942 final BasePermission p = mSettings.mPermissions.get(name);
943 if (p != null && p.perm != null) {
944 return PackageParser.generatePermissionInfo(p.perm, flags);
945 }
946 return null;
947 }
948 }
949
950 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
951 synchronized (mPackages) {
952 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
953 for (BasePermission p : mSettings.mPermissions.values()) {
954 if (group == null) {
955 if (p.perm.info.group == null) {
956 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
957 }
958 } else {
959 if (group.equals(p.perm.info.group)) {
960 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
961 }
962 }
963 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 if (out.size() > 0) {
966 return out;
967 }
968 return mPermissionGroups.containsKey(group) ? out : null;
969 }
970 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
973 synchronized (mPackages) {
974 return PackageParser.generatePermissionGroupInfo(
975 mPermissionGroups.get(name), flags);
976 }
977 }
978
979 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
980 synchronized (mPackages) {
981 final int N = mPermissionGroups.size();
982 ArrayList<PermissionGroupInfo> out
983 = new ArrayList<PermissionGroupInfo>(N);
984 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
985 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
986 }
987 return out;
988 }
989 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
992 PackageSetting ps = mSettings.mPackages.get(packageName);
993 if(ps != null) {
994 if(ps.pkg == null) {
995 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
996 if(pInfo != null) {
997 return pInfo.applicationInfo;
998 }
999 return null;
1000 }
1001 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1002 }
1003 return null;
1004 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1007 PackageSetting ps = mSettings.mPackages.get(packageName);
1008 if(ps != null) {
1009 if(ps.pkg == null) {
1010 ps.pkg = new PackageParser.Package(packageName);
1011 ps.pkg.applicationInfo.packageName = packageName;
1012 }
1013 return generatePackageInfo(ps.pkg, flags);
1014 }
1015 return null;
1016 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1019 synchronized (mPackages) {
1020 PackageParser.Package p = mPackages.get(packageName);
1021 if (Config.LOGV) Log.v(
1022 TAG, "getApplicationInfo " + packageName
1023 + ": " + p);
1024 if (p != null) {
1025 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001026 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 }
1028 if ("android".equals(packageName)||"system".equals(packageName)) {
1029 return mAndroidApplication;
1030 }
1031 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1032 return generateApplicationInfoFromSettingsLP(packageName, flags);
1033 }
1034 }
1035 return null;
1036 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001037
1038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1040 mContext.enforceCallingOrSelfPermission(
1041 android.Manifest.permission.CLEAR_APP_CACHE, null);
1042 // Queue up an async operation since clearing cache may take a little while.
1043 mHandler.post(new Runnable() {
1044 public void run() {
1045 mHandler.removeCallbacks(this);
1046 int retCode = -1;
1047 if (mInstaller != null) {
1048 retCode = mInstaller.freeCache(freeStorageSize);
1049 if (retCode < 0) {
1050 Log.w(TAG, "Couldn't clear application caches");
1051 }
1052 } //end if mInstaller
1053 if (observer != null) {
1054 try {
1055 observer.onRemoveCompleted(null, (retCode >= 0));
1056 } catch (RemoteException e) {
1057 Log.w(TAG, "RemoveException when invoking call back");
1058 }
1059 }
1060 }
1061 });
1062 }
1063
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001064 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001065 mContext.enforceCallingOrSelfPermission(
1066 android.Manifest.permission.CLEAR_APP_CACHE, null);
1067 // Queue up an async operation since clearing cache may take a little while.
1068 mHandler.post(new Runnable() {
1069 public void run() {
1070 mHandler.removeCallbacks(this);
1071 int retCode = -1;
1072 if (mInstaller != null) {
1073 retCode = mInstaller.freeCache(freeStorageSize);
1074 if (retCode < 0) {
1075 Log.w(TAG, "Couldn't clear application caches");
1076 }
1077 }
1078 if(pi != null) {
1079 try {
1080 // Callback via pending intent
1081 int code = (retCode >= 0) ? 1 : 0;
1082 pi.sendIntent(null, code, null,
1083 null, null);
1084 } catch (SendIntentException e1) {
1085 Log.i(TAG, "Failed to send pending intent");
1086 }
1087 }
1088 }
1089 });
1090 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1093 synchronized (mPackages) {
1094 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001095
1096 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001098 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 }
1100 if (mResolveComponentName.equals(component)) {
1101 return mResolveActivity;
1102 }
1103 }
1104 return null;
1105 }
1106
1107 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1108 synchronized (mPackages) {
1109 PackageParser.Activity a = mReceivers.mActivities.get(component);
1110 if (Config.LOGV) Log.v(
1111 TAG, "getReceiverInfo " + component + ": " + a);
1112 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1113 return PackageParser.generateActivityInfo(a, flags);
1114 }
1115 }
1116 return null;
1117 }
1118
1119 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1120 synchronized (mPackages) {
1121 PackageParser.Service s = mServices.mServices.get(component);
1122 if (Config.LOGV) Log.v(
1123 TAG, "getServiceInfo " + component + ": " + s);
1124 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1125 return PackageParser.generateServiceInfo(s, flags);
1126 }
1127 }
1128 return null;
1129 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 public String[] getSystemSharedLibraryNames() {
1132 Set<String> libSet;
1133 synchronized (mPackages) {
1134 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001135 int size = libSet.size();
1136 if (size > 0) {
1137 String[] libs = new String[size];
1138 libSet.toArray(libs);
1139 return libs;
1140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001142 return null;
1143 }
1144
1145 public FeatureInfo[] getSystemAvailableFeatures() {
1146 Collection<FeatureInfo> featSet;
1147 synchronized (mPackages) {
1148 featSet = mAvailableFeatures.values();
1149 int size = featSet.size();
1150 if (size > 0) {
1151 FeatureInfo[] features = new FeatureInfo[size+1];
1152 featSet.toArray(features);
1153 FeatureInfo fi = new FeatureInfo();
1154 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1155 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1156 features[size] = fi;
1157 return features;
1158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 }
1160 return null;
1161 }
1162
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001163 public boolean hasSystemFeature(String name) {
1164 synchronized (mPackages) {
1165 return mAvailableFeatures.containsKey(name);
1166 }
1167 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 public int checkPermission(String permName, String pkgName) {
1170 synchronized (mPackages) {
1171 PackageParser.Package p = mPackages.get(pkgName);
1172 if (p != null && p.mExtras != null) {
1173 PackageSetting ps = (PackageSetting)p.mExtras;
1174 if (ps.sharedUser != null) {
1175 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1176 return PackageManager.PERMISSION_GRANTED;
1177 }
1178 } else if (ps.grantedPermissions.contains(permName)) {
1179 return PackageManager.PERMISSION_GRANTED;
1180 }
1181 }
1182 }
1183 return PackageManager.PERMISSION_DENIED;
1184 }
1185
1186 public int checkUidPermission(String permName, int uid) {
1187 synchronized (mPackages) {
1188 Object obj = mSettings.getUserIdLP(uid);
1189 if (obj != null) {
1190 if (obj instanceof SharedUserSetting) {
1191 SharedUserSetting sus = (SharedUserSetting)obj;
1192 if (sus.grantedPermissions.contains(permName)) {
1193 return PackageManager.PERMISSION_GRANTED;
1194 }
1195 } else if (obj instanceof PackageSetting) {
1196 PackageSetting ps = (PackageSetting)obj;
1197 if (ps.grantedPermissions.contains(permName)) {
1198 return PackageManager.PERMISSION_GRANTED;
1199 }
1200 }
1201 } else {
1202 HashSet<String> perms = mSystemPermissions.get(uid);
1203 if (perms != null && perms.contains(permName)) {
1204 return PackageManager.PERMISSION_GRANTED;
1205 }
1206 }
1207 }
1208 return PackageManager.PERMISSION_DENIED;
1209 }
1210
1211 private BasePermission findPermissionTreeLP(String permName) {
1212 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1213 if (permName.startsWith(bp.name) &&
1214 permName.length() > bp.name.length() &&
1215 permName.charAt(bp.name.length()) == '.') {
1216 return bp;
1217 }
1218 }
1219 return null;
1220 }
1221
1222 private BasePermission checkPermissionTreeLP(String permName) {
1223 if (permName != null) {
1224 BasePermission bp = findPermissionTreeLP(permName);
1225 if (bp != null) {
1226 if (bp.uid == Binder.getCallingUid()) {
1227 return bp;
1228 }
1229 throw new SecurityException("Calling uid "
1230 + Binder.getCallingUid()
1231 + " is not allowed to add to permission tree "
1232 + bp.name + " owned by uid " + bp.uid);
1233 }
1234 }
1235 throw new SecurityException("No permission tree found for " + permName);
1236 }
1237
1238 public boolean addPermission(PermissionInfo info) {
1239 synchronized (mPackages) {
1240 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1241 throw new SecurityException("Label must be specified in permission");
1242 }
1243 BasePermission tree = checkPermissionTreeLP(info.name);
1244 BasePermission bp = mSettings.mPermissions.get(info.name);
1245 boolean added = bp == null;
1246 if (added) {
1247 bp = new BasePermission(info.name, tree.sourcePackage,
1248 BasePermission.TYPE_DYNAMIC);
1249 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1250 throw new SecurityException(
1251 "Not allowed to modify non-dynamic permission "
1252 + info.name);
1253 }
1254 bp.perm = new PackageParser.Permission(tree.perm.owner,
1255 new PermissionInfo(info));
1256 bp.perm.info.packageName = tree.perm.info.packageName;
1257 bp.uid = tree.uid;
1258 if (added) {
1259 mSettings.mPermissions.put(info.name, bp);
1260 }
1261 mSettings.writeLP();
1262 return added;
1263 }
1264 }
1265
1266 public void removePermission(String name) {
1267 synchronized (mPackages) {
1268 checkPermissionTreeLP(name);
1269 BasePermission bp = mSettings.mPermissions.get(name);
1270 if (bp != null) {
1271 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1272 throw new SecurityException(
1273 "Not allowed to modify non-dynamic permission "
1274 + name);
1275 }
1276 mSettings.mPermissions.remove(name);
1277 mSettings.writeLP();
1278 }
1279 }
1280 }
1281
Dianne Hackborn854060af2009-07-09 18:14:31 -07001282 public boolean isProtectedBroadcast(String actionName) {
1283 synchronized (mPackages) {
1284 return mProtectedBroadcasts.contains(actionName);
1285 }
1286 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 public int checkSignatures(String pkg1, String pkg2) {
1289 synchronized (mPackages) {
1290 PackageParser.Package p1 = mPackages.get(pkg1);
1291 PackageParser.Package p2 = mPackages.get(pkg2);
1292 if (p1 == null || p1.mExtras == null
1293 || p2 == null || p2.mExtras == null) {
1294 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1295 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001296 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 }
1298 }
1299
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001300 public int checkUidSignatures(int uid1, int uid2) {
1301 synchronized (mPackages) {
1302 Signature[] s1;
1303 Signature[] s2;
1304 Object obj = mSettings.getUserIdLP(uid1);
1305 if (obj != null) {
1306 if (obj instanceof SharedUserSetting) {
1307 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1308 } else if (obj instanceof PackageSetting) {
1309 s1 = ((PackageSetting)obj).signatures.mSignatures;
1310 } else {
1311 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1312 }
1313 } else {
1314 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1315 }
1316 obj = mSettings.getUserIdLP(uid2);
1317 if (obj != null) {
1318 if (obj instanceof SharedUserSetting) {
1319 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1320 } else if (obj instanceof PackageSetting) {
1321 s2 = ((PackageSetting)obj).signatures.mSignatures;
1322 } else {
1323 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1324 }
1325 } else {
1326 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1327 }
1328 return checkSignaturesLP(s1, s2);
1329 }
1330 }
1331
1332 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1333 if (s1 == null) {
1334 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1336 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1337 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001338 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1340 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001341 final int N1 = s1.length;
1342 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 for (int i=0; i<N1; i++) {
1344 boolean match = false;
1345 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001346 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 match = true;
1348 break;
1349 }
1350 }
1351 if (!match) {
1352 return PackageManager.SIGNATURE_NO_MATCH;
1353 }
1354 }
1355 return PackageManager.SIGNATURE_MATCH;
1356 }
1357
1358 public String[] getPackagesForUid(int uid) {
1359 synchronized (mPackages) {
1360 Object obj = mSettings.getUserIdLP(uid);
1361 if (obj instanceof SharedUserSetting) {
1362 SharedUserSetting sus = (SharedUserSetting)obj;
1363 final int N = sus.packages.size();
1364 String[] res = new String[N];
1365 Iterator<PackageSetting> it = sus.packages.iterator();
1366 int i=0;
1367 while (it.hasNext()) {
1368 res[i++] = it.next().name;
1369 }
1370 return res;
1371 } else if (obj instanceof PackageSetting) {
1372 PackageSetting ps = (PackageSetting)obj;
1373 return new String[] { ps.name };
1374 }
1375 }
1376 return null;
1377 }
1378
1379 public String getNameForUid(int uid) {
1380 synchronized (mPackages) {
1381 Object obj = mSettings.getUserIdLP(uid);
1382 if (obj instanceof SharedUserSetting) {
1383 SharedUserSetting sus = (SharedUserSetting)obj;
1384 return sus.name + ":" + sus.userId;
1385 } else if (obj instanceof PackageSetting) {
1386 PackageSetting ps = (PackageSetting)obj;
1387 return ps.name;
1388 }
1389 }
1390 return null;
1391 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 public int getUidForSharedUser(String sharedUserName) {
1394 if(sharedUserName == null) {
1395 return -1;
1396 }
1397 synchronized (mPackages) {
1398 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1399 if(suid == null) {
1400 return -1;
1401 }
1402 return suid.userId;
1403 }
1404 }
1405
1406 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1407 int flags) {
1408 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001409 return chooseBestActivity(intent, resolvedType, flags, query);
1410 }
1411
Mihai Predaeae850c2009-05-13 10:13:48 +02001412 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1413 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 if (query != null) {
1415 final int N = query.size();
1416 if (N == 1) {
1417 return query.get(0);
1418 } else if (N > 1) {
1419 // If there is more than one activity with the same priority,
1420 // then let the user decide between them.
1421 ResolveInfo r0 = query.get(0);
1422 ResolveInfo r1 = query.get(1);
1423 if (false) {
1424 System.out.println(r0.activityInfo.name +
1425 "=" + r0.priority + " vs " +
1426 r1.activityInfo.name +
1427 "=" + r1.priority);
1428 }
1429 // If the first activity has a higher priority, or a different
1430 // default, then it is always desireable to pick it.
1431 if (r0.priority != r1.priority
1432 || r0.preferredOrder != r1.preferredOrder
1433 || r0.isDefault != r1.isDefault) {
1434 return query.get(0);
1435 }
1436 // If we have saved a preference for a preferred activity for
1437 // this Intent, use that.
1438 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1439 flags, query, r0.priority);
1440 if (ri != null) {
1441 return ri;
1442 }
1443 return mResolveInfo;
1444 }
1445 }
1446 return null;
1447 }
1448
1449 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1450 int flags, List<ResolveInfo> query, int priority) {
1451 synchronized (mPackages) {
1452 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1453 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001454 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1456 if (prefs != null && prefs.size() > 0) {
1457 // First figure out how good the original match set is.
1458 // We will only allow preferred activities that came
1459 // from the same match quality.
1460 int match = 0;
1461 final int N = query.size();
1462 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1463 for (int j=0; j<N; j++) {
1464 ResolveInfo ri = query.get(j);
1465 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1466 + ": 0x" + Integer.toHexString(match));
1467 if (ri.match > match) match = ri.match;
1468 }
1469 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1470 + Integer.toHexString(match));
1471 match &= IntentFilter.MATCH_CATEGORY_MASK;
1472 final int M = prefs.size();
1473 for (int i=0; i<M; i++) {
1474 PreferredActivity pa = prefs.get(i);
1475 if (pa.mMatch != match) {
1476 continue;
1477 }
1478 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1479 if (DEBUG_PREFERRED) {
1480 Log.v(TAG, "Got preferred activity:");
1481 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1482 }
1483 if (ai != null) {
1484 for (int j=0; j<N; j++) {
1485 ResolveInfo ri = query.get(j);
1486 if (!ri.activityInfo.applicationInfo.packageName
1487 .equals(ai.applicationInfo.packageName)) {
1488 continue;
1489 }
1490 if (!ri.activityInfo.name.equals(ai.name)) {
1491 continue;
1492 }
1493
1494 // Okay we found a previously set preferred app.
1495 // If the result set is different from when this
1496 // was created, we need to clear it and re-ask the
1497 // user their preference.
1498 if (!pa.sameSet(query, priority)) {
1499 Log.i(TAG, "Result set changed, dropping preferred activity for "
1500 + intent + " type " + resolvedType);
1501 mSettings.mPreferredActivities.removeFilter(pa);
1502 return null;
1503 }
1504
1505 // Yay!
1506 return ri;
1507 }
1508 }
1509 }
1510 }
1511 }
1512 return null;
1513 }
1514
1515 public List<ResolveInfo> queryIntentActivities(Intent intent,
1516 String resolvedType, int flags) {
1517 ComponentName comp = intent.getComponent();
1518 if (comp != null) {
1519 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1520 ActivityInfo ai = getActivityInfo(comp, flags);
1521 if (ai != null) {
1522 ResolveInfo ri = new ResolveInfo();
1523 ri.activityInfo = ai;
1524 list.add(ri);
1525 }
1526 return list;
1527 }
1528
1529 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001530 String pkgName = intent.getPackage();
1531 if (pkgName == null) {
1532 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1533 resolvedType, flags);
1534 }
1535 PackageParser.Package pkg = mPackages.get(pkgName);
1536 if (pkg != null) {
1537 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1538 resolvedType, flags, pkg.activities);
1539 }
1540 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 }
1542 }
1543
1544 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1545 Intent[] specifics, String[] specificTypes, Intent intent,
1546 String resolvedType, int flags) {
1547 final String resultsAction = intent.getAction();
1548
1549 List<ResolveInfo> results = queryIntentActivities(
1550 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1551 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1552
1553 int specificsPos = 0;
1554 int N;
1555
1556 // todo: note that the algorithm used here is O(N^2). This
1557 // isn't a problem in our current environment, but if we start running
1558 // into situations where we have more than 5 or 10 matches then this
1559 // should probably be changed to something smarter...
1560
1561 // First we go through and resolve each of the specific items
1562 // that were supplied, taking care of removing any corresponding
1563 // duplicate items in the generic resolve list.
1564 if (specifics != null) {
1565 for (int i=0; i<specifics.length; i++) {
1566 final Intent sintent = specifics[i];
1567 if (sintent == null) {
1568 continue;
1569 }
1570
1571 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1572 String action = sintent.getAction();
1573 if (resultsAction != null && resultsAction.equals(action)) {
1574 // If this action was explicitly requested, then don't
1575 // remove things that have it.
1576 action = null;
1577 }
1578 ComponentName comp = sintent.getComponent();
1579 ResolveInfo ri = null;
1580 ActivityInfo ai = null;
1581 if (comp == null) {
1582 ri = resolveIntent(
1583 sintent,
1584 specificTypes != null ? specificTypes[i] : null,
1585 flags);
1586 if (ri == null) {
1587 continue;
1588 }
1589 if (ri == mResolveInfo) {
1590 // ACK! Must do something better with this.
1591 }
1592 ai = ri.activityInfo;
1593 comp = new ComponentName(ai.applicationInfo.packageName,
1594 ai.name);
1595 } else {
1596 ai = getActivityInfo(comp, flags);
1597 if (ai == null) {
1598 continue;
1599 }
1600 }
1601
1602 // Look for any generic query activities that are duplicates
1603 // of this specific one, and remove them from the results.
1604 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1605 N = results.size();
1606 int j;
1607 for (j=specificsPos; j<N; j++) {
1608 ResolveInfo sri = results.get(j);
1609 if ((sri.activityInfo.name.equals(comp.getClassName())
1610 && sri.activityInfo.applicationInfo.packageName.equals(
1611 comp.getPackageName()))
1612 || (action != null && sri.filter.matchAction(action))) {
1613 results.remove(j);
1614 if (Config.LOGV) Log.v(
1615 TAG, "Removing duplicate item from " + j
1616 + " due to specific " + specificsPos);
1617 if (ri == null) {
1618 ri = sri;
1619 }
1620 j--;
1621 N--;
1622 }
1623 }
1624
1625 // Add this specific item to its proper place.
1626 if (ri == null) {
1627 ri = new ResolveInfo();
1628 ri.activityInfo = ai;
1629 }
1630 results.add(specificsPos, ri);
1631 ri.specificIndex = i;
1632 specificsPos++;
1633 }
1634 }
1635
1636 // Now we go through the remaining generic results and remove any
1637 // duplicate actions that are found here.
1638 N = results.size();
1639 for (int i=specificsPos; i<N-1; i++) {
1640 final ResolveInfo rii = results.get(i);
1641 if (rii.filter == null) {
1642 continue;
1643 }
1644
1645 // Iterate over all of the actions of this result's intent
1646 // filter... typically this should be just one.
1647 final Iterator<String> it = rii.filter.actionsIterator();
1648 if (it == null) {
1649 continue;
1650 }
1651 while (it.hasNext()) {
1652 final String action = it.next();
1653 if (resultsAction != null && resultsAction.equals(action)) {
1654 // If this action was explicitly requested, then don't
1655 // remove things that have it.
1656 continue;
1657 }
1658 for (int j=i+1; j<N; j++) {
1659 final ResolveInfo rij = results.get(j);
1660 if (rij.filter != null && rij.filter.hasAction(action)) {
1661 results.remove(j);
1662 if (Config.LOGV) Log.v(
1663 TAG, "Removing duplicate item from " + j
1664 + " due to action " + action + " at " + i);
1665 j--;
1666 N--;
1667 }
1668 }
1669 }
1670
1671 // If the caller didn't request filter information, drop it now
1672 // so we don't have to marshall/unmarshall it.
1673 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1674 rii.filter = null;
1675 }
1676 }
1677
1678 // Filter out the caller activity if so requested.
1679 if (caller != null) {
1680 N = results.size();
1681 for (int i=0; i<N; i++) {
1682 ActivityInfo ainfo = results.get(i).activityInfo;
1683 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1684 && caller.getClassName().equals(ainfo.name)) {
1685 results.remove(i);
1686 break;
1687 }
1688 }
1689 }
1690
1691 // If the caller didn't request filter information,
1692 // drop them now so we don't have to
1693 // marshall/unmarshall it.
1694 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1695 N = results.size();
1696 for (int i=0; i<N; i++) {
1697 results.get(i).filter = null;
1698 }
1699 }
1700
1701 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1702 return results;
1703 }
1704
1705 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1706 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001707 ComponentName comp = intent.getComponent();
1708 if (comp != null) {
1709 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1710 ActivityInfo ai = getReceiverInfo(comp, flags);
1711 if (ai != null) {
1712 ResolveInfo ri = new ResolveInfo();
1713 ri.activityInfo = ai;
1714 list.add(ri);
1715 }
1716 return list;
1717 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001720 String pkgName = intent.getPackage();
1721 if (pkgName == null) {
1722 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1723 resolvedType, flags);
1724 }
1725 PackageParser.Package pkg = mPackages.get(pkgName);
1726 if (pkg != null) {
1727 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1728 resolvedType, flags, pkg.receivers);
1729 }
1730 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 }
1732 }
1733
1734 public ResolveInfo resolveService(Intent intent, String resolvedType,
1735 int flags) {
1736 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1737 flags);
1738 if (query != null) {
1739 if (query.size() >= 1) {
1740 // If there is more than one service with the same priority,
1741 // just arbitrarily pick the first one.
1742 return query.get(0);
1743 }
1744 }
1745 return null;
1746 }
1747
1748 public List<ResolveInfo> queryIntentServices(Intent intent,
1749 String resolvedType, int flags) {
1750 ComponentName comp = intent.getComponent();
1751 if (comp != null) {
1752 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1753 ServiceInfo si = getServiceInfo(comp, flags);
1754 if (si != null) {
1755 ResolveInfo ri = new ResolveInfo();
1756 ri.serviceInfo = si;
1757 list.add(ri);
1758 }
1759 return list;
1760 }
1761
1762 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001763 String pkgName = intent.getPackage();
1764 if (pkgName == null) {
1765 return (List<ResolveInfo>)mServices.queryIntent(intent,
1766 resolvedType, flags);
1767 }
1768 PackageParser.Package pkg = mPackages.get(pkgName);
1769 if (pkg != null) {
1770 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1771 resolvedType, flags, pkg.services);
1772 }
1773 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 public List<PackageInfo> getInstalledPackages(int flags) {
1778 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1779
1780 synchronized (mPackages) {
1781 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1782 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1783 while (i.hasNext()) {
1784 final PackageSetting ps = i.next();
1785 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1786 if(psPkg != null) {
1787 finalList.add(psPkg);
1788 }
1789 }
1790 }
1791 else {
1792 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1793 while (i.hasNext()) {
1794 final PackageParser.Package p = i.next();
1795 if (p.applicationInfo != null) {
1796 PackageInfo pi = generatePackageInfo(p, flags);
1797 if(pi != null) {
1798 finalList.add(pi);
1799 }
1800 }
1801 }
1802 }
1803 }
1804 return finalList;
1805 }
1806
1807 public List<ApplicationInfo> getInstalledApplications(int flags) {
1808 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1809 synchronized(mPackages) {
1810 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1811 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1812 while (i.hasNext()) {
1813 final PackageSetting ps = i.next();
1814 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1815 if(ai != null) {
1816 finalList.add(ai);
1817 }
1818 }
1819 }
1820 else {
1821 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1822 while (i.hasNext()) {
1823 final PackageParser.Package p = i.next();
1824 if (p.applicationInfo != null) {
1825 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1826 if(ai != null) {
1827 finalList.add(ai);
1828 }
1829 }
1830 }
1831 }
1832 }
1833 return finalList;
1834 }
1835
1836 public List<ApplicationInfo> getPersistentApplications(int flags) {
1837 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1838
1839 synchronized (mPackages) {
1840 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1841 while (i.hasNext()) {
1842 PackageParser.Package p = i.next();
1843 if (p.applicationInfo != null
1844 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1845 && (!mSafeMode || (p.applicationInfo.flags
1846 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1847 finalList.add(p.applicationInfo);
1848 }
1849 }
1850 }
1851
1852 return finalList;
1853 }
1854
1855 public ProviderInfo resolveContentProvider(String name, int flags) {
1856 synchronized (mPackages) {
1857 final PackageParser.Provider provider = mProviders.get(name);
1858 return provider != null
1859 && mSettings.isEnabledLP(provider.info, flags)
1860 && (!mSafeMode || (provider.info.applicationInfo.flags
1861 &ApplicationInfo.FLAG_SYSTEM) != 0)
1862 ? PackageParser.generateProviderInfo(provider, flags)
1863 : null;
1864 }
1865 }
1866
Fred Quintana718d8a22009-04-29 17:53:20 -07001867 /**
1868 * @deprecated
1869 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 public void querySyncProviders(List outNames, List outInfo) {
1871 synchronized (mPackages) {
1872 Iterator<Map.Entry<String, PackageParser.Provider>> i
1873 = mProviders.entrySet().iterator();
1874
1875 while (i.hasNext()) {
1876 Map.Entry<String, PackageParser.Provider> entry = i.next();
1877 PackageParser.Provider p = entry.getValue();
1878
1879 if (p.syncable
1880 && (!mSafeMode || (p.info.applicationInfo.flags
1881 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1882 outNames.add(entry.getKey());
1883 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1884 }
1885 }
1886 }
1887 }
1888
1889 public List<ProviderInfo> queryContentProviders(String processName,
1890 int uid, int flags) {
1891 ArrayList<ProviderInfo> finalList = null;
1892
1893 synchronized (mPackages) {
1894 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
1895 while (i.hasNext()) {
1896 PackageParser.Provider p = i.next();
1897 if (p.info.authority != null
1898 && (processName == null ||
1899 (p.info.processName.equals(processName)
1900 && p.info.applicationInfo.uid == uid))
1901 && mSettings.isEnabledLP(p.info, flags)
1902 && (!mSafeMode || (p.info.applicationInfo.flags
1903 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1904 if (finalList == null) {
1905 finalList = new ArrayList<ProviderInfo>(3);
1906 }
1907 finalList.add(PackageParser.generateProviderInfo(p,
1908 flags));
1909 }
1910 }
1911 }
1912
1913 if (finalList != null) {
1914 Collections.sort(finalList, mProviderInitOrderSorter);
1915 }
1916
1917 return finalList;
1918 }
1919
1920 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
1921 int flags) {
1922 synchronized (mPackages) {
1923 final PackageParser.Instrumentation i = mInstrumentation.get(name);
1924 return PackageParser.generateInstrumentationInfo(i, flags);
1925 }
1926 }
1927
1928 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
1929 int flags) {
1930 ArrayList<InstrumentationInfo> finalList =
1931 new ArrayList<InstrumentationInfo>();
1932
1933 synchronized (mPackages) {
1934 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
1935 while (i.hasNext()) {
1936 PackageParser.Instrumentation p = i.next();
1937 if (targetPackage == null
1938 || targetPackage.equals(p.info.targetPackage)) {
1939 finalList.add(PackageParser.generateInstrumentationInfo(p,
1940 flags));
1941 }
1942 }
1943 }
1944
1945 return finalList;
1946 }
1947
1948 private void scanDirLI(File dir, int flags, int scanMode) {
1949 Log.d(TAG, "Scanning app dir " + dir);
1950
1951 String[] files = dir.list();
1952
1953 int i;
1954 for (i=0; i<files.length; i++) {
1955 File file = new File(dir, files[i]);
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07001956 File resFile = file;
1957 // Pick up the resource path from settings for fwd locked apps
1958 if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
1959 resFile = null;
1960 }
1961 PackageParser.Package pkg = scanPackageLI(file, file, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
1963 }
1964 }
1965
1966 private static void reportSettingsProblem(int priority, String msg) {
1967 try {
1968 File dataDir = Environment.getDataDirectory();
1969 File systemDir = new File(dataDir, "system");
1970 File fname = new File(systemDir, "uiderrors.txt");
1971 FileOutputStream out = new FileOutputStream(fname, true);
1972 PrintWriter pw = new PrintWriter(out);
1973 pw.println(msg);
1974 pw.close();
1975 FileUtils.setPermissions(
1976 fname.toString(),
1977 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
1978 -1, -1);
1979 } catch (java.io.IOException e) {
1980 }
1981 Log.println(priority, TAG, msg);
1982 }
1983
1984 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
1985 PackageParser.Package pkg, File srcFile, int parseFlags) {
1986 if (GET_CERTIFICATES) {
1987 if (ps == null || !ps.codePath.equals(srcFile)
1988 || ps.getTimeStamp() != srcFile.lastModified()) {
1989 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
1990 if (!pp.collectCertificates(pkg, parseFlags)) {
1991 mLastScanError = pp.getParseError();
1992 return false;
1993 }
1994 }
1995 }
1996 return true;
1997 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 /*
2000 * Scan a package and return the newly parsed package.
2001 * Returns null in case of errors and the error code is stored in mLastScanError
2002 */
2003 private PackageParser.Package scanPackageLI(File scanFile,
2004 File destCodeFile, File destResourceFile, int parseFlags,
2005 int scanMode) {
2006 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2007 parseFlags |= mDefParseFlags;
2008 PackageParser pp = new PackageParser(scanFile.getPath());
2009 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 final PackageParser.Package pkg = pp.parsePackage(scanFile,
2011 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
2012 if (pkg == null) {
2013 mLastScanError = pp.getParseError();
2014 return null;
2015 }
2016 PackageSetting ps;
2017 PackageSetting updatedPkg;
2018 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002019 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2021 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002022 // Verify certificates first
2023 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2024 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2025 return null;
2026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 if (updatedPkg != null) {
2028 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2029 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2030 }
2031 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2032 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002033 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2034 if (pkg.mVersionCode < ps.versionCode) {
2035 // The system package has been updated and the code path does not match
2036 // Ignore entry. Just return
2037 Log.w(TAG, "Package:" + pkg.packageName +
2038 " has been updated. Ignoring the one from path:"+scanFile);
2039 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2040 return null;
2041 } else {
2042 // Delete the older apk pointed to by ps
2043 // At this point, its safely assumed that package installation for
2044 // apps in system partition will go through. If not there won't be a working
2045 // version of the app
2046 synchronized (mPackages) {
2047 // Just remove the loaded entries from package lists.
2048 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002049 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002050 deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
2051 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 }
2054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 // The apk is forward locked (not public) if its code and resources
2056 // are kept in different files.
2057 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
2058 scanMode |= SCAN_FORWARD_LOCKED;
2059 }
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002060 File resFile = destResourceFile;
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002061 if (ps != null && ((scanMode & SCAN_FORWARD_LOCKED) != 0)) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002062 resFile = getFwdLockedResource(ps.name);
2063 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002065 return scanPackageLI(scanFile, destCodeFile, resFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
2067 }
2068
2069 private static String fixProcessName(String defProcessName,
2070 String processName, int uid) {
2071 if (processName == null) {
2072 return defProcessName;
2073 }
2074 return processName;
2075 }
2076
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002077 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2079 if (pkg.mSignatures != null) {
2080 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2081 updateSignature)) {
2082 Log.e(TAG, "Package " + pkg.packageName
2083 + " signatures do not match the previously installed version; ignoring!");
2084 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2085 return false;
2086 }
2087
2088 if (pkgSetting.sharedUser != null) {
2089 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2090 pkg.mSignatures, updateSignature)) {
2091 Log.e(TAG, "Package " + pkg.packageName
2092 + " has no signatures that match those in shared user "
2093 + pkgSetting.sharedUser.name + "; ignoring!");
2094 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2095 return false;
2096 }
2097 }
2098 } else {
2099 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2100 }
2101 return true;
2102 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002103
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002104 public boolean performDexOpt(String packageName) {
2105 if (!mNoDexOpt) {
2106 return false;
2107 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002108
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002109 PackageParser.Package p;
2110 synchronized (mPackages) {
2111 p = mPackages.get(packageName);
2112 if (p == null || p.mDidDexOpt) {
2113 return false;
2114 }
2115 }
2116 synchronized (mInstallLock) {
2117 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2118 }
2119 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002120
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002121 static final int DEX_OPT_SKIPPED = 0;
2122 static final int DEX_OPT_PERFORMED = 1;
2123 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002124
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002125 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2126 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002127 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002128 String path = pkg.mScanPath;
2129 int ret = 0;
2130 try {
2131 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002132 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002133 !pkg.mForwardLocked);
2134 pkg.mDidDexOpt = true;
2135 performed = true;
2136 }
2137 } catch (FileNotFoundException e) {
2138 Log.w(TAG, "Apk not found for dexopt: " + path);
2139 ret = -1;
2140 } catch (IOException e) {
2141 Log.w(TAG, "Exception reading apk: " + path, e);
2142 ret = -1;
2143 }
2144 if (ret < 0) {
2145 //error from installer
2146 return DEX_OPT_FAILED;
2147 }
2148 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002149
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002150 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2151 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 private PackageParser.Package scanPackageLI(
2154 File scanFile, File destCodeFile, File destResourceFile,
2155 PackageParser.Package pkg, int parseFlags, int scanMode) {
2156
2157 mScanningPath = scanFile;
2158 if (pkg == null) {
2159 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2160 return null;
2161 }
2162
2163 final String pkgName = pkg.applicationInfo.packageName;
2164 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2165 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2166 }
2167
2168 if (pkgName.equals("android")) {
2169 synchronized (mPackages) {
2170 if (mAndroidApplication != null) {
2171 Log.w(TAG, "*************************************************");
2172 Log.w(TAG, "Core android package being redefined. Skipping.");
2173 Log.w(TAG, " file=" + mScanningPath);
2174 Log.w(TAG, "*************************************************");
2175 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2176 return null;
2177 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 // Set up information for our fall-back user intent resolution
2180 // activity.
2181 mPlatformPackage = pkg;
2182 pkg.mVersionCode = mSdkVersion;
2183 mAndroidApplication = pkg.applicationInfo;
2184 mResolveActivity.applicationInfo = mAndroidApplication;
2185 mResolveActivity.name = ResolverActivity.class.getName();
2186 mResolveActivity.packageName = mAndroidApplication.packageName;
2187 mResolveActivity.processName = mAndroidApplication.processName;
2188 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2189 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2190 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2191 mResolveActivity.exported = true;
2192 mResolveActivity.enabled = true;
2193 mResolveInfo.activityInfo = mResolveActivity;
2194 mResolveInfo.priority = 0;
2195 mResolveInfo.preferredOrder = 0;
2196 mResolveInfo.match = 0;
2197 mResolveComponentName = new ComponentName(
2198 mAndroidApplication.packageName, mResolveActivity.name);
2199 }
2200 }
2201
2202 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2203 TAG, "Scanning package " + pkgName);
2204 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2205 Log.w(TAG, "*************************************************");
2206 Log.w(TAG, "Application package " + pkgName
2207 + " already installed. Skipping duplicate.");
2208 Log.w(TAG, "*************************************************");
2209 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2210 return null;
2211 }
2212
2213 SharedUserSetting suid = null;
2214 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 synchronized (mPackages) {
2219 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002220 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2221 if (mTmpSharedLibraries == null ||
2222 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2223 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2224 }
2225 int num = 0;
2226 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2227 for (int i=0; i<N; i++) {
2228 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002229 if (file == null) {
2230 Log.e(TAG, "Package " + pkg.packageName
2231 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002232 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2234 return null;
2235 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002236 mTmpSharedLibraries[num] = file;
2237 num++;
2238 }
2239 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2240 for (int i=0; i<N; i++) {
2241 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2242 if (file == null) {
2243 Log.w(TAG, "Package " + pkg.packageName
2244 + " desires unavailable shared library "
2245 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2246 } else {
2247 mTmpSharedLibraries[num] = file;
2248 num++;
2249 }
2250 }
2251 if (num > 0) {
2252 pkg.usesLibraryFiles = new String[num];
2253 System.arraycopy(mTmpSharedLibraries, 0,
2254 pkg.usesLibraryFiles, 0, num);
2255 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002256
Dianne Hackborn49237342009-08-27 20:08:01 -07002257 if (pkg.reqFeatures != null) {
2258 N = pkg.reqFeatures.size();
2259 for (int i=0; i<N; i++) {
2260 FeatureInfo fi = pkg.reqFeatures.get(i);
2261 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2262 // Don't care.
2263 continue;
2264 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002265
Dianne Hackborn49237342009-08-27 20:08:01 -07002266 if (fi.name != null) {
2267 if (mAvailableFeatures.get(fi.name) == null) {
2268 Log.e(TAG, "Package " + pkg.packageName
2269 + " requires unavailable feature "
2270 + fi.name + "; failing!");
2271 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2272 return null;
2273 }
2274 }
2275 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 }
2277 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 if (pkg.mSharedUserId != null) {
2280 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2281 pkg.applicationInfo.flags, true);
2282 if (suid == null) {
2283 Log.w(TAG, "Creating application package " + pkgName
2284 + " for shared user failed");
2285 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2286 return null;
2287 }
2288 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2289 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2290 + suid.userId + "): packages=" + suid.packages);
2291 }
2292 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002293
2294 // Just create the setting, don't add it yet. For already existing packages
2295 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2297 destResourceFile, pkg.applicationInfo.flags, true, false);
2298 if (pkgSetting == null) {
2299 Log.w(TAG, "Creating application package " + pkgName + " failed");
2300 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2301 return null;
2302 }
2303 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2304 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2305 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002307 pkg.applicationInfo.uid = pkgSetting.userId;
2308 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002309
2310 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2312 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2313 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2314 return null;
2315 }
2316 // The signature has changed, but this package is in the system
2317 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002318 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002319 // However... if this package is part of a shared user, but it
2320 // doesn't match the signature of the shared user, let's fail.
2321 // What this means is that you can't change the signatures
2322 // associated with an overall shared user, which doesn't seem all
2323 // that unreasonable.
2324 if (pkgSetting.sharedUser != null) {
2325 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2326 pkg.mSignatures, false)) {
2327 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2328 return null;
2329 }
2330 }
2331 removeExisting = true;
2332 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002333
The Android Open Source Project10592532009-03-18 17:39:46 -07002334 // Verify that this new package doesn't have any content providers
2335 // that conflict with existing packages. Only do this if the
2336 // package isn't already installed, since we don't want to break
2337 // things that are installed.
2338 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2339 int N = pkg.providers.size();
2340 int i;
2341 for (i=0; i<N; i++) {
2342 PackageParser.Provider p = pkg.providers.get(i);
2343 String names[] = p.info.authority.split(";");
2344 for (int j = 0; j < names.length; j++) {
2345 if (mProviders.containsKey(names[j])) {
2346 PackageParser.Provider other = mProviders.get(names[j]);
2347 Log.w(TAG, "Can't install because provider name " + names[j] +
2348 " (in package " + pkg.applicationInfo.packageName +
2349 ") is already used by "
2350 + ((other != null && other.component != null)
2351 ? other.component.getPackageName() : "?"));
2352 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2353 return null;
2354 }
2355 }
2356 }
2357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 }
2359
2360 if (removeExisting) {
2361 if (mInstaller != null) {
2362 int ret = mInstaller.remove(pkgName);
2363 if (ret != 0) {
2364 String msg = "System package " + pkg.packageName
2365 + " could not have data directory erased after signature change.";
2366 reportSettingsProblem(Log.WARN, msg);
2367 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2368 return null;
2369 }
2370 }
2371 Log.w(TAG, "System package " + pkg.packageName
2372 + " signature changed: existing data removed.");
2373 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2374 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 long scanFileTime = scanFile.lastModified();
2377 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2378 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2379 pkg.applicationInfo.processName = fixProcessName(
2380 pkg.applicationInfo.packageName,
2381 pkg.applicationInfo.processName,
2382 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002383 pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384
2385 File dataPath;
2386 if (mPlatformPackage == pkg) {
2387 // The system package is special.
2388 dataPath = new File (Environment.getDataDirectory(), "system");
2389 pkg.applicationInfo.dataDir = dataPath.getPath();
2390 } else {
2391 // This is a normal package, need to make its data directory.
2392 dataPath = new File(mAppDataDir, pkgName);
2393 if (dataPath.exists()) {
2394 mOutPermissions[1] = 0;
2395 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2396 if (mOutPermissions[1] == pkg.applicationInfo.uid
2397 || !Process.supportsProcesses()) {
2398 pkg.applicationInfo.dataDir = dataPath.getPath();
2399 } else {
2400 boolean recovered = false;
2401 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2402 // If this is a system app, we can at least delete its
2403 // current data so the application will still work.
2404 if (mInstaller != null) {
2405 int ret = mInstaller.remove(pkgName);
2406 if(ret >= 0) {
2407 // Old data gone!
2408 String msg = "System package " + pkg.packageName
2409 + " has changed from uid: "
2410 + mOutPermissions[1] + " to "
2411 + pkg.applicationInfo.uid + "; old data erased";
2412 reportSettingsProblem(Log.WARN, msg);
2413 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 // And now re-install the app.
2416 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2417 pkg.applicationInfo.uid);
2418 if (ret == -1) {
2419 // Ack should not happen!
2420 msg = "System package " + pkg.packageName
2421 + " could not have data directory re-created after delete.";
2422 reportSettingsProblem(Log.WARN, msg);
2423 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2424 return null;
2425 }
2426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002428 if (!recovered) {
2429 mHasSystemUidErrors = true;
2430 }
2431 }
2432 if (!recovered) {
2433 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2434 + pkg.applicationInfo.uid + "/fs_"
2435 + mOutPermissions[1];
2436 String msg = "Package " + pkg.packageName
2437 + " has mismatched uid: "
2438 + mOutPermissions[1] + " on disk, "
2439 + pkg.applicationInfo.uid + " in settings";
2440 synchronized (mPackages) {
2441 if (!mReportedUidError) {
2442 mReportedUidError = true;
2443 msg = msg + "; read messages:\n"
2444 + mSettings.getReadMessagesLP();
2445 }
2446 reportSettingsProblem(Log.ERROR, msg);
2447 }
2448 }
2449 }
2450 pkg.applicationInfo.dataDir = dataPath.getPath();
2451 } else {
2452 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2453 Log.v(TAG, "Want this data dir: " + dataPath);
2454 //invoke installer to do the actual installation
2455 if (mInstaller != null) {
2456 int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
2457 pkg.applicationInfo.uid);
2458 if(ret < 0) {
2459 // Error from installer
2460 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2461 return null;
2462 }
2463 } else {
2464 dataPath.mkdirs();
2465 if (dataPath.exists()) {
2466 FileUtils.setPermissions(
2467 dataPath.toString(),
2468 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2469 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2470 }
2471 }
2472 if (dataPath.exists()) {
2473 pkg.applicationInfo.dataDir = dataPath.getPath();
2474 } else {
2475 Log.w(TAG, "Unable to create data directory: " + dataPath);
2476 pkg.applicationInfo.dataDir = null;
2477 }
2478 }
2479 }
2480
2481 // Perform shared library installation and dex validation and
2482 // optimization, if this is not a system app.
2483 if (mInstaller != null) {
2484 String path = scanFile.getPath();
2485 if (scanFileNewer) {
2486 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002487 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2488 if (err != PackageManager.INSTALL_SUCCEEDED) {
2489 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490 return null;
2491 }
2492 }
2493
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002494 pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
2495 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002496
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002497 if ((scanMode&SCAN_NO_DEX) == 0) {
2498 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2500 return null;
2501 }
2502 }
2503 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002505 if (mFactoryTest && pkg.requestedPermissions.contains(
2506 android.Manifest.permission.FACTORY_TEST)) {
2507 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2508 }
2509
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002510 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002511 if ((scanMode&SCAN_MONITOR) != 0) {
2512 pkg.mPath = destCodeFile.getAbsolutePath();
2513 mAppDirs.put(pkg.mPath, pkg);
2514 }
2515
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002516 // Request the ActivityManager to kill the process(only for existing packages)
2517 // so that we do not end up in a confused state while the user is still using the older
2518 // version of the application while the new one gets installed.
2519 IActivityManager am = ActivityManagerNative.getDefault();
2520 if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
2521 try {
2522 am.killApplicationWithUid(pkg.applicationInfo.packageName,
2523 pkg.applicationInfo.uid);
2524 } catch (RemoteException e) {
2525 }
2526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002528 // Add the new setting to mSettings
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002529 mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002531 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 int N = pkg.providers.size();
2533 StringBuilder r = null;
2534 int i;
2535 for (i=0; i<N; i++) {
2536 PackageParser.Provider p = pkg.providers.get(i);
2537 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2538 p.info.processName, pkg.applicationInfo.uid);
2539 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2540 p.info.name), p);
2541 p.syncable = p.info.isSyncable;
2542 String names[] = p.info.authority.split(";");
2543 p.info.authority = null;
2544 for (int j = 0; j < names.length; j++) {
2545 if (j == 1 && p.syncable) {
2546 // We only want the first authority for a provider to possibly be
2547 // syncable, so if we already added this provider using a different
2548 // authority clear the syncable flag. We copy the provider before
2549 // changing it because the mProviders object contains a reference
2550 // to a provider that we don't want to change.
2551 // Only do this for the second authority since the resulting provider
2552 // object can be the same for all future authorities for this provider.
2553 p = new PackageParser.Provider(p);
2554 p.syncable = false;
2555 }
2556 if (!mProviders.containsKey(names[j])) {
2557 mProviders.put(names[j], p);
2558 if (p.info.authority == null) {
2559 p.info.authority = names[j];
2560 } else {
2561 p.info.authority = p.info.authority + ";" + names[j];
2562 }
2563 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2564 Log.d(TAG, "Registered content provider: " + names[j] +
2565 ", className = " + p.info.name +
2566 ", isSyncable = " + p.info.isSyncable);
2567 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002568 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 Log.w(TAG, "Skipping provider name " + names[j] +
2570 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002571 "): name already used by "
2572 + ((other != null && other.component != null)
2573 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002574 }
2575 }
2576 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2577 if (r == null) {
2578 r = new StringBuilder(256);
2579 } else {
2580 r.append(' ');
2581 }
2582 r.append(p.info.name);
2583 }
2584 }
2585 if (r != null) {
2586 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2587 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002589 N = pkg.services.size();
2590 r = null;
2591 for (i=0; i<N; i++) {
2592 PackageParser.Service s = pkg.services.get(i);
2593 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2594 s.info.processName, pkg.applicationInfo.uid);
2595 mServices.addService(s);
2596 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2597 if (r == null) {
2598 r = new StringBuilder(256);
2599 } else {
2600 r.append(' ');
2601 }
2602 r.append(s.info.name);
2603 }
2604 }
2605 if (r != null) {
2606 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2607 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 N = pkg.receivers.size();
2610 r = null;
2611 for (i=0; i<N; i++) {
2612 PackageParser.Activity a = pkg.receivers.get(i);
2613 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2614 a.info.processName, pkg.applicationInfo.uid);
2615 mReceivers.addActivity(a, "receiver");
2616 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2617 if (r == null) {
2618 r = new StringBuilder(256);
2619 } else {
2620 r.append(' ');
2621 }
2622 r.append(a.info.name);
2623 }
2624 }
2625 if (r != null) {
2626 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2627 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 N = pkg.activities.size();
2630 r = null;
2631 for (i=0; i<N; i++) {
2632 PackageParser.Activity a = pkg.activities.get(i);
2633 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2634 a.info.processName, pkg.applicationInfo.uid);
2635 mActivities.addActivity(a, "activity");
2636 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2637 if (r == null) {
2638 r = new StringBuilder(256);
2639 } else {
2640 r.append(' ');
2641 }
2642 r.append(a.info.name);
2643 }
2644 }
2645 if (r != null) {
2646 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2647 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 N = pkg.permissionGroups.size();
2650 r = null;
2651 for (i=0; i<N; i++) {
2652 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2653 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2654 if (cur == null) {
2655 mPermissionGroups.put(pg.info.name, pg);
2656 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2657 if (r == null) {
2658 r = new StringBuilder(256);
2659 } else {
2660 r.append(' ');
2661 }
2662 r.append(pg.info.name);
2663 }
2664 } else {
2665 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2666 + pg.info.packageName + " ignored: original from "
2667 + cur.info.packageName);
2668 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2669 if (r == null) {
2670 r = new StringBuilder(256);
2671 } else {
2672 r.append(' ');
2673 }
2674 r.append("DUP:");
2675 r.append(pg.info.name);
2676 }
2677 }
2678 }
2679 if (r != null) {
2680 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2681 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 N = pkg.permissions.size();
2684 r = null;
2685 for (i=0; i<N; i++) {
2686 PackageParser.Permission p = pkg.permissions.get(i);
2687 HashMap<String, BasePermission> permissionMap =
2688 p.tree ? mSettings.mPermissionTrees
2689 : mSettings.mPermissions;
2690 p.group = mPermissionGroups.get(p.info.group);
2691 if (p.info.group == null || p.group != null) {
2692 BasePermission bp = permissionMap.get(p.info.name);
2693 if (bp == null) {
2694 bp = new BasePermission(p.info.name, p.info.packageName,
2695 BasePermission.TYPE_NORMAL);
2696 permissionMap.put(p.info.name, bp);
2697 }
2698 if (bp.perm == null) {
2699 if (bp.sourcePackage == null
2700 || bp.sourcePackage.equals(p.info.packageName)) {
2701 BasePermission tree = findPermissionTreeLP(p.info.name);
2702 if (tree == null
2703 || tree.sourcePackage.equals(p.info.packageName)) {
2704 bp.perm = p;
2705 bp.uid = pkg.applicationInfo.uid;
2706 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2707 if (r == null) {
2708 r = new StringBuilder(256);
2709 } else {
2710 r.append(' ');
2711 }
2712 r.append(p.info.name);
2713 }
2714 } else {
2715 Log.w(TAG, "Permission " + p.info.name + " from package "
2716 + p.info.packageName + " ignored: base tree "
2717 + tree.name + " is from package "
2718 + tree.sourcePackage);
2719 }
2720 } else {
2721 Log.w(TAG, "Permission " + p.info.name + " from package "
2722 + p.info.packageName + " ignored: original from "
2723 + bp.sourcePackage);
2724 }
2725 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2726 if (r == null) {
2727 r = new StringBuilder(256);
2728 } else {
2729 r.append(' ');
2730 }
2731 r.append("DUP:");
2732 r.append(p.info.name);
2733 }
2734 } else {
2735 Log.w(TAG, "Permission " + p.info.name + " from package "
2736 + p.info.packageName + " ignored: no group "
2737 + p.group);
2738 }
2739 }
2740 if (r != null) {
2741 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 N = pkg.instrumentation.size();
2745 r = null;
2746 for (i=0; i<N; i++) {
2747 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2748 a.info.packageName = pkg.applicationInfo.packageName;
2749 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2750 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2751 a.info.dataDir = pkg.applicationInfo.dataDir;
2752 mInstrumentation.put(a.component, a);
2753 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2754 if (r == null) {
2755 r = new StringBuilder(256);
2756 } else {
2757 r.append(' ');
2758 }
2759 r.append(a.info.name);
2760 }
2761 }
2762 if (r != null) {
2763 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2764 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002765
Dianne Hackborn854060af2009-07-09 18:14:31 -07002766 if (pkg.protectedBroadcasts != null) {
2767 N = pkg.protectedBroadcasts.size();
2768 for (i=0; i<N; i++) {
2769 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2770 }
2771 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 pkgSetting.setTimeStamp(scanFileTime);
2774 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 return pkg;
2777 }
2778
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002779 // The following constants are returned by cachePackageSharedLibsForAbiLI
2780 // to indicate if native shared libraries were found in the package.
2781 // Values are:
2782 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2783 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2784 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2785 // in package (and not installed)
2786 //
2787 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2788 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2789 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002791 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2792 // and automatically copy them to /data/data/<appname>/lib if present.
2793 //
2794 // NOTE: this method may throw an IOException if the library cannot
2795 // be copied to its final destination, e.g. if there isn't enough
2796 // room left on the data partition, or a ZipException if the package
2797 // file is malformed.
2798 //
2799 private int cachePackageSharedLibsForAbiLI( PackageParser.Package pkg,
2800 File dataPath, File scanFile, String cpuAbi)
2801 throws IOException, ZipException {
2802 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2803 final String apkLib = "lib/";
2804 final int apkLibLen = apkLib.length();
2805 final int cpuAbiLen = cpuAbi.length();
2806 final String libPrefix = "lib";
2807 final int libPrefixLen = libPrefix.length();
2808 final String libSuffix = ".so";
2809 final int libSuffixLen = libSuffix.length();
2810 boolean hasNativeLibraries = false;
2811 boolean installedNativeLibraries = false;
2812
2813 // the minimum length of a valid native shared library of the form
2814 // lib/<something>/lib<name>.so.
2815 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2816
2817 ZipFile zipFile = new ZipFile(scanFile);
2818 Enumeration<ZipEntry> entries =
2819 (Enumeration<ZipEntry>) zipFile.entries();
2820
2821 while (entries.hasMoreElements()) {
2822 ZipEntry entry = entries.nextElement();
2823 // skip directories
2824 if (entry.isDirectory()) {
2825 continue;
2826 }
2827 String entryName = entry.getName();
2828
2829 // check that the entry looks like lib/<something>/lib<name>.so
2830 // here, but don't check the ABI just yet.
2831 //
2832 // - must be sufficiently long
2833 // - must end with libSuffix, i.e. ".so"
2834 // - must start with apkLib, i.e. "lib/"
2835 if (entryName.length() < minEntryLen ||
2836 !entryName.endsWith(libSuffix) ||
2837 !entryName.startsWith(apkLib) ) {
2838 continue;
2839 }
2840
2841 // file name must start with libPrefix, i.e. "lib"
2842 int lastSlash = entryName.lastIndexOf('/');
2843
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002844 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002845 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2846 continue;
2847 }
2848
2849 hasNativeLibraries = true;
2850
2851 // check the cpuAbi now, between lib/ and /lib<name>.so
2852 //
2853 if (lastSlash != apkLibLen + cpuAbiLen ||
2854 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2855 continue;
2856
2857 // extract the library file name, ensure it doesn't contain
2858 // weird characters. we're guaranteed here that it doesn't contain
2859 // a directory separator though.
2860 String libFileName = entryName.substring(lastSlash+1);
2861 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2862 continue;
2863 }
2864
2865 installedNativeLibraries = true;
2866
2867 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
2868 File.separator + libFileName;
2869 File sharedLibraryFile = new File(sharedLibraryFilePath);
2870 if (! sharedLibraryFile.exists() ||
2871 sharedLibraryFile.length() != entry.getSize() ||
2872 sharedLibraryFile.lastModified() != entry.getTime()) {
2873 if (Config.LOGD) {
2874 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002876 if (mInstaller == null) {
2877 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07002878 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002879 cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
2880 sharedLibraryFile);
2881 }
2882 }
2883 if (!hasNativeLibraries)
2884 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
2885
2886 if (!installedNativeLibraries)
2887 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
2888
2889 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
2890 }
2891
2892 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
2893 // and copy them to /data/data/<appname>/lib.
2894 //
2895 // This function will first try the main CPU ABI defined by Build.CPU_ABI
2896 // (which corresponds to ro.product.cpu.abi), and also try an alternate
2897 // one if ro.product.cpu.abi2 is defined.
2898 //
2899 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
2900 File dataPath, File scanFile) {
2901 final String cpuAbi = Build.CPU_ABI;
2902 try {
2903 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
2904
2905 // some architectures are capable of supporting several CPU ABIs
2906 // for example, 'armeabi-v7a' also supports 'armeabi' native code
2907 // this is indicated by the definition of the ro.product.cpu.abi2
2908 // system property.
2909 //
2910 // only scan the package twice in case of ABI mismatch
2911 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2912 String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
2913 if (cpuAbi2 != null) {
2914 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002915 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002916
2917 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
2918 Log.w(TAG,"Native ABI mismatch from package file");
2919 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920 }
2921 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002922 } catch (ZipException e) {
2923 Log.w(TAG, "Failed to extract data from package file", e);
2924 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07002926 Log.w(TAG, "Failed to cache package shared libs", e);
2927 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07002929 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002930 }
2931
2932 private void cacheSharedLibLI(PackageParser.Package pkg,
2933 ZipFile zipFile, ZipEntry entry,
2934 File sharedLibraryDir,
2935 File sharedLibraryFile) throws IOException {
2936 InputStream inputStream = zipFile.getInputStream(entry);
2937 try {
2938 File tempFile = File.createTempFile("tmp", "tmp", sharedLibraryDir);
2939 String tempFilePath = tempFile.getPath();
2940 // XXX package manager can't change owner, so the lib files for
2941 // now need to be left as world readable and owned by the system.
2942 if (! FileUtils.copyToFile(inputStream, tempFile) ||
2943 ! tempFile.setLastModified(entry.getTime()) ||
2944 FileUtils.setPermissions(tempFilePath,
2945 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
2946 |FileUtils.S_IROTH, -1, -1) != 0 ||
2947 ! tempFile.renameTo(sharedLibraryFile)) {
2948 // Failed to properly write file.
2949 tempFile.delete();
2950 throw new IOException("Couldn't create cached shared lib "
2951 + sharedLibraryFile + " in " + sharedLibraryDir);
2952 }
2953 } finally {
2954 inputStream.close();
2955 }
2956 }
2957
2958 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
2959 if (chatty && Config.LOGD) Log.d(
2960 TAG, "Removing package " + pkg.applicationInfo.packageName );
2961
2962 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 mPackages.remove(pkg.applicationInfo.packageName);
2966 if (pkg.mPath != null) {
2967 mAppDirs.remove(pkg.mPath);
2968 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 PackageSetting ps = (PackageSetting)pkg.mExtras;
2971 if (ps != null && ps.sharedUser != null) {
2972 // XXX don't do this until the data is removed.
2973 if (false) {
2974 ps.sharedUser.packages.remove(ps);
2975 if (ps.sharedUser.packages.size() == 0) {
2976 // Remove.
2977 }
2978 }
2979 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 int N = pkg.providers.size();
2982 StringBuilder r = null;
2983 int i;
2984 for (i=0; i<N; i++) {
2985 PackageParser.Provider p = pkg.providers.get(i);
2986 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
2987 p.info.name));
2988 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 /* The is another ContentProvider with this authority when
2991 * this app was installed so this authority is null,
2992 * Ignore it as we don't have to unregister the provider.
2993 */
2994 continue;
2995 }
2996 String names[] = p.info.authority.split(";");
2997 for (int j = 0; j < names.length; j++) {
2998 if (mProviders.get(names[j]) == p) {
2999 mProviders.remove(names[j]);
3000 if (chatty && Config.LOGD) Log.d(
3001 TAG, "Unregistered content provider: " + names[j] +
3002 ", className = " + p.info.name +
3003 ", isSyncable = " + p.info.isSyncable);
3004 }
3005 }
3006 if (chatty) {
3007 if (r == null) {
3008 r = new StringBuilder(256);
3009 } else {
3010 r.append(' ');
3011 }
3012 r.append(p.info.name);
3013 }
3014 }
3015 if (r != null) {
3016 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3017 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 N = pkg.services.size();
3020 r = null;
3021 for (i=0; i<N; i++) {
3022 PackageParser.Service s = pkg.services.get(i);
3023 mServices.removeService(s);
3024 if (chatty) {
3025 if (r == null) {
3026 r = new StringBuilder(256);
3027 } else {
3028 r.append(' ');
3029 }
3030 r.append(s.info.name);
3031 }
3032 }
3033 if (r != null) {
3034 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3035 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 N = pkg.receivers.size();
3038 r = null;
3039 for (i=0; i<N; i++) {
3040 PackageParser.Activity a = pkg.receivers.get(i);
3041 mReceivers.removeActivity(a, "receiver");
3042 if (chatty) {
3043 if (r == null) {
3044 r = new StringBuilder(256);
3045 } else {
3046 r.append(' ');
3047 }
3048 r.append(a.info.name);
3049 }
3050 }
3051 if (r != null) {
3052 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3053 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 N = pkg.activities.size();
3056 r = null;
3057 for (i=0; i<N; i++) {
3058 PackageParser.Activity a = pkg.activities.get(i);
3059 mActivities.removeActivity(a, "activity");
3060 if (chatty) {
3061 if (r == null) {
3062 r = new StringBuilder(256);
3063 } else {
3064 r.append(' ');
3065 }
3066 r.append(a.info.name);
3067 }
3068 }
3069 if (r != null) {
3070 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3071 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003073 N = pkg.permissions.size();
3074 r = null;
3075 for (i=0; i<N; i++) {
3076 PackageParser.Permission p = pkg.permissions.get(i);
3077 boolean tree = false;
3078 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3079 if (bp == null) {
3080 tree = true;
3081 bp = mSettings.mPermissionTrees.get(p.info.name);
3082 }
3083 if (bp != null && bp.perm == p) {
3084 if (bp.type != BasePermission.TYPE_BUILTIN) {
3085 if (tree) {
3086 mSettings.mPermissionTrees.remove(p.info.name);
3087 } else {
3088 mSettings.mPermissions.remove(p.info.name);
3089 }
3090 } else {
3091 bp.perm = null;
3092 }
3093 if (chatty) {
3094 if (r == null) {
3095 r = new StringBuilder(256);
3096 } else {
3097 r.append(' ');
3098 }
3099 r.append(p.info.name);
3100 }
3101 }
3102 }
3103 if (r != null) {
3104 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3105 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 N = pkg.instrumentation.size();
3108 r = null;
3109 for (i=0; i<N; i++) {
3110 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3111 mInstrumentation.remove(a.component);
3112 if (chatty) {
3113 if (r == null) {
3114 r = new StringBuilder(256);
3115 } else {
3116 r.append(' ');
3117 }
3118 r.append(a.info.name);
3119 }
3120 }
3121 if (r != null) {
3122 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3123 }
3124 }
3125 }
3126
3127 private static final boolean isPackageFilename(String name) {
3128 return name != null && name.endsWith(".apk");
3129 }
3130
3131 private void updatePermissionsLP() {
3132 // Make sure there are no dangling permission trees.
3133 Iterator<BasePermission> it = mSettings.mPermissionTrees
3134 .values().iterator();
3135 while (it.hasNext()) {
3136 BasePermission bp = it.next();
3137 if (bp.perm == null) {
3138 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3139 + " from package " + bp.sourcePackage);
3140 it.remove();
3141 }
3142 }
3143
3144 // Make sure all dynamic permissions have been assigned to a package,
3145 // and make sure there are no dangling permissions.
3146 it = mSettings.mPermissions.values().iterator();
3147 while (it.hasNext()) {
3148 BasePermission bp = it.next();
3149 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3150 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3151 + bp.name + " pkg=" + bp.sourcePackage
3152 + " info=" + bp.pendingInfo);
3153 if (bp.perm == null && bp.pendingInfo != null) {
3154 BasePermission tree = findPermissionTreeLP(bp.name);
3155 if (tree != null) {
3156 bp.perm = new PackageParser.Permission(tree.perm.owner,
3157 new PermissionInfo(bp.pendingInfo));
3158 bp.perm.info.packageName = tree.perm.info.packageName;
3159 bp.perm.info.name = bp.name;
3160 bp.uid = tree.uid;
3161 }
3162 }
3163 }
3164 if (bp.perm == null) {
3165 Log.w(TAG, "Removing dangling permission: " + bp.name
3166 + " from package " + bp.sourcePackage);
3167 it.remove();
3168 }
3169 }
3170
3171 // Now update the permissions for all packages, in particular
3172 // replace the granted permissions of the system packages.
3173 for (PackageParser.Package pkg : mPackages.values()) {
3174 grantPermissionsLP(pkg, false);
3175 }
3176 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3179 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3180 if (ps == null) {
3181 return;
3182 }
3183 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3184 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 if (replace) {
3187 ps.permissionsFixed = false;
3188 if (gp == ps) {
3189 gp.grantedPermissions.clear();
3190 gp.gids = mGlobalGids;
3191 }
3192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 if (gp.gids == null) {
3195 gp.gids = mGlobalGids;
3196 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 final int N = pkg.requestedPermissions.size();
3199 for (int i=0; i<N; i++) {
3200 String name = pkg.requestedPermissions.get(i);
3201 BasePermission bp = mSettings.mPermissions.get(name);
3202 PackageParser.Permission p = bp != null ? bp.perm : null;
3203 if (false) {
3204 if (gp != ps) {
3205 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3206 + ": " + p);
3207 }
3208 }
3209 if (p != null) {
3210 final String perm = p.info.name;
3211 boolean allowed;
3212 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3213 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3214 allowed = true;
3215 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3216 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003217 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003219 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003220 == PackageManager.SIGNATURE_MATCH);
3221 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3222 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3223 // For updated system applications, the signatureOrSystem permission
3224 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003225 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3227 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3228 if(sysPs.grantedPermissions.contains(perm)) {
3229 allowed = true;
3230 } else {
3231 allowed = false;
3232 }
3233 } else {
3234 allowed = true;
3235 }
3236 }
3237 }
3238 } else {
3239 allowed = false;
3240 }
3241 if (false) {
3242 if (gp != ps) {
3243 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3244 }
3245 }
3246 if (allowed) {
3247 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3248 && ps.permissionsFixed) {
3249 // If this is an existing, non-system package, then
3250 // we can't add any new permissions to it.
3251 if (!gp.loadedPermissions.contains(perm)) {
3252 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003253 // Except... if this is a permission that was added
3254 // to the platform (note: need to only do this when
3255 // updating the platform).
3256 final int NP = PackageParser.NEW_PERMISSIONS.length;
3257 for (int ip=0; ip<NP; ip++) {
3258 final PackageParser.NewPermissionInfo npi
3259 = PackageParser.NEW_PERMISSIONS[ip];
3260 if (npi.name.equals(perm)
3261 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3262 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003263 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003264 + pkg.packageName);
3265 break;
3266 }
3267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 }
3269 }
3270 if (allowed) {
3271 if (!gp.grantedPermissions.contains(perm)) {
3272 addedPermission = true;
3273 gp.grantedPermissions.add(perm);
3274 gp.gids = appendInts(gp.gids, bp.gids);
3275 }
3276 } else {
3277 Log.w(TAG, "Not granting permission " + perm
3278 + " to package " + pkg.packageName
3279 + " because it was previously installed without");
3280 }
3281 } else {
3282 Log.w(TAG, "Not granting permission " + perm
3283 + " to package " + pkg.packageName
3284 + " (protectionLevel=" + p.info.protectionLevel
3285 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3286 + ")");
3287 }
3288 } else {
3289 Log.w(TAG, "Unknown permission " + name
3290 + " in package " + pkg.packageName);
3291 }
3292 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003295 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3296 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003297 // This is the first that we have heard about this package, so the
3298 // permissions we have now selected are fixed until explicitly
3299 // changed.
3300 ps.permissionsFixed = true;
3301 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3302 }
3303 }
3304
3305 private final class ActivityIntentResolver
3306 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003307 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003309 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 }
3311
Mihai Preda074edef2009-05-18 17:13:31 +02003312 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003314 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003315 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3316 }
3317
Mihai Predaeae850c2009-05-13 10:13:48 +02003318 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3319 ArrayList<PackageParser.Activity> packageActivities) {
3320 if (packageActivities == null) {
3321 return null;
3322 }
3323 mFlags = flags;
3324 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3325 int N = packageActivities.size();
3326 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3327 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003328
3329 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003330 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003331 intentFilters = packageActivities.get(i).intents;
3332 if (intentFilters != null && intentFilters.size() > 0) {
3333 listCut.add(intentFilters);
3334 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003335 }
3336 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3337 }
3338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 public final void addActivity(PackageParser.Activity a, String type) {
3340 mActivities.put(a.component, a);
3341 if (SHOW_INFO || Config.LOGV) Log.v(
3342 TAG, " " + type + " " +
3343 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3344 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3345 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003346 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3348 if (SHOW_INFO || Config.LOGV) {
3349 Log.v(TAG, " IntentFilter:");
3350 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3351 }
3352 if (!intent.debugCheck()) {
3353 Log.w(TAG, "==> For Activity " + a.info.name);
3354 }
3355 addFilter(intent);
3356 }
3357 }
3358
3359 public final void removeActivity(PackageParser.Activity a, String type) {
3360 mActivities.remove(a.component);
3361 if (SHOW_INFO || Config.LOGV) Log.v(
3362 TAG, " " + type + " " +
3363 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3364 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3365 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003366 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3368 if (SHOW_INFO || Config.LOGV) {
3369 Log.v(TAG, " IntentFilter:");
3370 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3371 }
3372 removeFilter(intent);
3373 }
3374 }
3375
3376 @Override
3377 protected boolean allowFilterResult(
3378 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3379 ActivityInfo filterAi = filter.activity.info;
3380 for (int i=dest.size()-1; i>=0; i--) {
3381 ActivityInfo destAi = dest.get(i).activityInfo;
3382 if (destAi.name == filterAi.name
3383 && destAi.packageName == filterAi.packageName) {
3384 return false;
3385 }
3386 }
3387 return true;
3388 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003390 @Override
3391 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3392 int match) {
3393 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3394 return null;
3395 }
3396 final PackageParser.Activity activity = info.activity;
3397 if (mSafeMode && (activity.info.applicationInfo.flags
3398 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3399 return null;
3400 }
3401 final ResolveInfo res = new ResolveInfo();
3402 res.activityInfo = PackageParser.generateActivityInfo(activity,
3403 mFlags);
3404 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3405 res.filter = info;
3406 }
3407 res.priority = info.getPriority();
3408 res.preferredOrder = activity.owner.mPreferredOrder;
3409 //System.out.println("Result: " + res.activityInfo.className +
3410 // " = " + res.priority);
3411 res.match = match;
3412 res.isDefault = info.hasDefault;
3413 res.labelRes = info.labelRes;
3414 res.nonLocalizedLabel = info.nonLocalizedLabel;
3415 res.icon = info.icon;
3416 return res;
3417 }
3418
3419 @Override
3420 protected void sortResults(List<ResolveInfo> results) {
3421 Collections.sort(results, mResolvePrioritySorter);
3422 }
3423
3424 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003425 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003426 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003427 out.print(prefix); out.print(
3428 Integer.toHexString(System.identityHashCode(filter.activity)));
3429 out.print(' ');
3430 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 }
3432
3433// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3434// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3435// final List<ResolveInfo> retList = Lists.newArrayList();
3436// while (i.hasNext()) {
3437// final ResolveInfo resolveInfo = i.next();
3438// if (isEnabledLP(resolveInfo.activityInfo)) {
3439// retList.add(resolveInfo);
3440// }
3441// }
3442// return retList;
3443// }
3444
3445 // Keys are String (activity class name), values are Activity.
3446 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3447 = new HashMap<ComponentName, PackageParser.Activity>();
3448 private int mFlags;
3449 }
3450
3451 private final class ServiceIntentResolver
3452 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003453 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003454 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003455 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 }
3457
Mihai Preda074edef2009-05-18 17:13:31 +02003458 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003459 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003460 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003461 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3462 }
3463
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003464 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3465 ArrayList<PackageParser.Service> packageServices) {
3466 if (packageServices == null) {
3467 return null;
3468 }
3469 mFlags = flags;
3470 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3471 int N = packageServices.size();
3472 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3473 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3474
3475 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3476 for (int i = 0; i < N; ++i) {
3477 intentFilters = packageServices.get(i).intents;
3478 if (intentFilters != null && intentFilters.size() > 0) {
3479 listCut.add(intentFilters);
3480 }
3481 }
3482 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3483 }
3484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485 public final void addService(PackageParser.Service s) {
3486 mServices.put(s.component, s);
3487 if (SHOW_INFO || Config.LOGV) Log.v(
3488 TAG, " " + (s.info.nonLocalizedLabel != null
3489 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3490 if (SHOW_INFO || Config.LOGV) Log.v(
3491 TAG, " Class=" + s.info.name);
3492 int NI = s.intents.size();
3493 int j;
3494 for (j=0; j<NI; j++) {
3495 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3496 if (SHOW_INFO || Config.LOGV) {
3497 Log.v(TAG, " IntentFilter:");
3498 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3499 }
3500 if (!intent.debugCheck()) {
3501 Log.w(TAG, "==> For Service " + s.info.name);
3502 }
3503 addFilter(intent);
3504 }
3505 }
3506
3507 public final void removeService(PackageParser.Service s) {
3508 mServices.remove(s.component);
3509 if (SHOW_INFO || Config.LOGV) Log.v(
3510 TAG, " " + (s.info.nonLocalizedLabel != null
3511 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3512 if (SHOW_INFO || Config.LOGV) Log.v(
3513 TAG, " Class=" + s.info.name);
3514 int NI = s.intents.size();
3515 int j;
3516 for (j=0; j<NI; j++) {
3517 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3518 if (SHOW_INFO || Config.LOGV) {
3519 Log.v(TAG, " IntentFilter:");
3520 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3521 }
3522 removeFilter(intent);
3523 }
3524 }
3525
3526 @Override
3527 protected boolean allowFilterResult(
3528 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3529 ServiceInfo filterSi = filter.service.info;
3530 for (int i=dest.size()-1; i>=0; i--) {
3531 ServiceInfo destAi = dest.get(i).serviceInfo;
3532 if (destAi.name == filterSi.name
3533 && destAi.packageName == filterSi.packageName) {
3534 return false;
3535 }
3536 }
3537 return true;
3538 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 @Override
3541 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3542 int match) {
3543 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3544 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3545 return null;
3546 }
3547 final PackageParser.Service service = info.service;
3548 if (mSafeMode && (service.info.applicationInfo.flags
3549 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3550 return null;
3551 }
3552 final ResolveInfo res = new ResolveInfo();
3553 res.serviceInfo = PackageParser.generateServiceInfo(service,
3554 mFlags);
3555 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3556 res.filter = filter;
3557 }
3558 res.priority = info.getPriority();
3559 res.preferredOrder = service.owner.mPreferredOrder;
3560 //System.out.println("Result: " + res.activityInfo.className +
3561 // " = " + res.priority);
3562 res.match = match;
3563 res.isDefault = info.hasDefault;
3564 res.labelRes = info.labelRes;
3565 res.nonLocalizedLabel = info.nonLocalizedLabel;
3566 res.icon = info.icon;
3567 return res;
3568 }
3569
3570 @Override
3571 protected void sortResults(List<ResolveInfo> results) {
3572 Collections.sort(results, mResolvePrioritySorter);
3573 }
3574
3575 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003576 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003578 out.print(prefix); out.print(
3579 Integer.toHexString(System.identityHashCode(filter.service)));
3580 out.print(' ');
3581 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 }
3583
3584// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3585// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3586// final List<ResolveInfo> retList = Lists.newArrayList();
3587// while (i.hasNext()) {
3588// final ResolveInfo resolveInfo = (ResolveInfo) i;
3589// if (isEnabledLP(resolveInfo.serviceInfo)) {
3590// retList.add(resolveInfo);
3591// }
3592// }
3593// return retList;
3594// }
3595
3596 // Keys are String (activity class name), values are Activity.
3597 private final HashMap<ComponentName, PackageParser.Service> mServices
3598 = new HashMap<ComponentName, PackageParser.Service>();
3599 private int mFlags;
3600 };
3601
3602 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3603 new Comparator<ResolveInfo>() {
3604 public int compare(ResolveInfo r1, ResolveInfo r2) {
3605 int v1 = r1.priority;
3606 int v2 = r2.priority;
3607 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3608 if (v1 != v2) {
3609 return (v1 > v2) ? -1 : 1;
3610 }
3611 v1 = r1.preferredOrder;
3612 v2 = r2.preferredOrder;
3613 if (v1 != v2) {
3614 return (v1 > v2) ? -1 : 1;
3615 }
3616 if (r1.isDefault != r2.isDefault) {
3617 return r1.isDefault ? -1 : 1;
3618 }
3619 v1 = r1.match;
3620 v2 = r2.match;
3621 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3622 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3623 }
3624 };
3625
3626 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3627 new Comparator<ProviderInfo>() {
3628 public int compare(ProviderInfo p1, ProviderInfo p2) {
3629 final int v1 = p1.initOrder;
3630 final int v2 = p2.initOrder;
3631 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3632 }
3633 };
3634
3635 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3636 IActivityManager am = ActivityManagerNative.getDefault();
3637 if (am != null) {
3638 try {
3639 final Intent intent = new Intent(action,
3640 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3641 if (extras != null) {
3642 intent.putExtras(extras);
3643 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003644 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003645 am.broadcastIntent(
3646 null, intent,
3647 null, null, 0, null, null, null, false, false);
3648 } catch (RemoteException ex) {
3649 }
3650 }
3651 }
3652
3653 private final class AppDirObserver extends FileObserver {
3654 public AppDirObserver(String path, int mask, boolean isrom) {
3655 super(path, mask);
3656 mRootDir = path;
3657 mIsRom = isrom;
3658 }
3659
3660 public void onEvent(int event, String path) {
3661 String removedPackage = null;
3662 int removedUid = -1;
3663 String addedPackage = null;
3664 int addedUid = -1;
3665
3666 synchronized (mInstallLock) {
3667 String fullPathStr = null;
3668 File fullPath = null;
3669 if (path != null) {
3670 fullPath = new File(mRootDir, path);
3671 fullPathStr = fullPath.getPath();
3672 }
3673
3674 if (Config.LOGV) Log.v(
3675 TAG, "File " + fullPathStr + " changed: "
3676 + Integer.toHexString(event));
3677
3678 if (!isPackageFilename(path)) {
3679 if (Config.LOGV) Log.v(
3680 TAG, "Ignoring change of non-package file: " + fullPathStr);
3681 return;
3682 }
3683
3684 if ((event&REMOVE_EVENTS) != 0) {
3685 synchronized (mInstallLock) {
3686 PackageParser.Package p = mAppDirs.get(fullPathStr);
3687 if (p != null) {
3688 removePackageLI(p, true);
3689 removedPackage = p.applicationInfo.packageName;
3690 removedUid = p.applicationInfo.uid;
3691 }
3692 }
3693 }
3694
3695 if ((event&ADD_EVENTS) != 0) {
3696 PackageParser.Package p = mAppDirs.get(fullPathStr);
3697 if (p == null) {
3698 p = scanPackageLI(fullPath, fullPath, fullPath,
3699 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3700 PackageParser.PARSE_CHATTY |
3701 PackageParser.PARSE_MUST_BE_APK,
3702 SCAN_MONITOR);
3703 if (p != null) {
3704 synchronized (mPackages) {
3705 grantPermissionsLP(p, false);
3706 }
3707 addedPackage = p.applicationInfo.packageName;
3708 addedUid = p.applicationInfo.uid;
3709 }
3710 }
3711 }
3712
3713 synchronized (mPackages) {
3714 mSettings.writeLP();
3715 }
3716 }
3717
3718 if (removedPackage != null) {
3719 Bundle extras = new Bundle(1);
3720 extras.putInt(Intent.EXTRA_UID, removedUid);
3721 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3722 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3723 }
3724 if (addedPackage != null) {
3725 Bundle extras = new Bundle(1);
3726 extras.putInt(Intent.EXTRA_UID, addedUid);
3727 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3728 }
3729 }
3730
3731 private final String mRootDir;
3732 private final boolean mIsRom;
3733 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 /* Called when a downloaded package installation has been confirmed by the user */
3736 public void installPackage(
3737 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003738 installPackage(packageURI, observer, flags, null);
3739 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003740
Jacek Surazski65e13172009-04-28 15:26:38 +02003741 /* Called when a downloaded package installation has been confirmed by the user */
3742 public void installPackage(
3743 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3744 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 mContext.enforceCallingOrSelfPermission(
3746 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003748 // Queue up an async operation since the package installation may take a little while.
3749 mHandler.post(new Runnable() {
3750 public void run() {
3751 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003752 // Result object to be returned
3753 PackageInstalledInfo res = new PackageInstalledInfo();
3754 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
3755 res.uid = -1;
3756 res.pkg = null;
3757 res.removedInfo = new PackageRemovedInfo();
3758 // Make a temporary copy of file from given packageURI
3759 File tmpPackageFile = copyTempInstallFile(packageURI, res);
3760 if (tmpPackageFile != null) {
3761 synchronized (mInstallLock) {
3762 installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
3763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 }
3765 if (observer != null) {
3766 try {
3767 observer.packageInstalled(res.name, res.returnCode);
3768 } catch (RemoteException e) {
3769 Log.i(TAG, "Observer no longer exists.");
3770 }
3771 }
3772 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3773 // call appears in the synchronized block above.
3774 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3775 res.removedInfo.sendBroadcast(false, true);
3776 Bundle extras = new Bundle(1);
3777 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003778 final boolean update = res.removedInfo.removedPackage != null;
3779 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003780 extras.putBoolean(Intent.EXTRA_REPLACING, true);
3781 }
3782 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
3783 res.pkg.applicationInfo.packageName,
3784 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07003785 if (update) {
3786 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
3787 res.pkg.applicationInfo.packageName,
3788 extras);
3789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003790 }
3791 Runtime.getRuntime().gc();
3792 }
3793 });
3794 }
3795
3796 class PackageInstalledInfo {
3797 String name;
3798 int uid;
3799 PackageParser.Package pkg;
3800 int returnCode;
3801 PackageRemovedInfo removedInfo;
3802 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 /*
3805 * Install a non-existing package.
3806 */
3807 private void installNewPackageLI(String pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003808 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003810 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003811 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003812 // Remember this for later, in case we need to rollback this install
3813 boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
3814 res.name = pkgName;
3815 synchronized(mPackages) {
3816 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(destFilePath)) {
3817 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003818 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 + " without first uninstalling.");
3820 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
3821 return;
3822 }
3823 }
3824 if (destPackageFile.exists()) {
3825 // It's safe to do this because we know (from the above check) that the file
3826 // isn't currently used for an installed package.
3827 destPackageFile.delete();
3828 }
3829 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3830 PackageParser.Package newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3831 destResourceFile, pkg, 0,
3832 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003833 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003834 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3835 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 if (newPackage == null) {
3837 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3838 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3839 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3840 }
3841 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003842 updateSettingsLI(pkgName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003844 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 newPackage,
3846 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02003847 forwardLocked,
3848 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003849 res);
3850 // delete the partially installed application. the data directory will have to be
3851 // restored if it was already existing
3852 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3853 // remove package from internal structures. Note that we want deletePackageX to
3854 // delete the package data and cache directories that it created in
3855 // scanPackageLocked, unless those directories existed before we even tried to
3856 // install.
3857 deletePackageLI(
3858 pkgName, true,
3859 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
3860 res.removedInfo);
3861 }
3862 }
3863 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 private void replacePackageLI(String pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003866 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003868 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003869 String installerPackageName, PackageInstalledInfo res) {
3870
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003871 PackageParser.Package oldPackage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 // First find the old package info and check signatures
3873 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003874 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003875 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
3876 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
3878 return;
3879 }
3880 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003881 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 if(sysPkg) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003883 replaceSystemPackageLI(oldPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003884 tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003885 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003886 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 } else {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07003888 replaceNonSystemPackageLI(oldPackage, tmpPackageFile, destFilePath,
The Android Open Source Project10592532009-03-18 17:39:46 -07003889 destPackageFile, destResourceFile, pkg, forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003890 newInstall, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
3892 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003894 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003895 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07003897 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02003898 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003899 PackageParser.Package newPackage = null;
3900 String pkgName = deletedPackage.packageName;
3901 boolean deletedPkg = true;
3902 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003903
Jacek Surazski65e13172009-04-28 15:26:38 +02003904 String oldInstallerPackageName = null;
3905 synchronized (mPackages) {
3906 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
3907 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003908
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003909 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003910 // First delete the existing package while retaining the data directory
3911 if (!deletePackageLI(pkgName, false, PackageManager.DONT_DELETE_DATA,
3912 res.removedInfo)) {
3913 // If the existing package was'nt successfully deleted
3914 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
3915 deletedPkg = false;
3916 } else {
3917 // Successfully deleted the old package. Now proceed with re-installation
3918 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
3919 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
3920 destResourceFile, pkg, parseFlags,
3921 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003922 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07003923 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
3924 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 if (newPackage == null) {
3926 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
3927 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
3928 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
3929 }
3930 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003931 updateSettingsLI(pkgName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003933 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 newPackage,
3935 true,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003936 forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02003937 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 res);
3939 updatedSettings = true;
3940 }
3941 }
3942
3943 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3944 // If we deleted an exisiting package, the old source and resource files that we
3945 // were keeping around in case we needed them (see below) can now be deleted
3946 final ApplicationInfo deletedPackageAppInfo = deletedPackage.applicationInfo;
3947 final ApplicationInfo installedPackageAppInfo =
3948 newPackage.applicationInfo;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07003949 deletePackageResourcesLI(pkgName,
3950 !deletedPackageAppInfo.sourceDir
3951 .equals(installedPackageAppInfo.sourceDir)
3952 ? deletedPackageAppInfo.sourceDir : null,
3953 !deletedPackageAppInfo.publicSourceDir
3954 .equals(installedPackageAppInfo.publicSourceDir)
3955 ? deletedPackageAppInfo.publicSourceDir : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003956 //update signature on the new package setting
3957 //this should always succeed, since we checked the
3958 //signature earlier.
3959 synchronized(mPackages) {
3960 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
3961 parseFlags, true);
3962 }
3963 } else {
3964 // remove package from internal structures. Note that we want deletePackageX to
3965 // delete the package data and cache directories that it created in
3966 // scanPackageLocked, unless those directories existed before we even tried to
3967 // install.
3968 if(updatedSettings) {
3969 deletePackageLI(
3970 pkgName, true,
3971 PackageManager.DONT_DELETE_DATA,
3972 res.removedInfo);
3973 }
3974 // Since we failed to install the new package we need to restore the old
3975 // package that we deleted.
3976 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003977 File restoreFile = new File(deletedPackage.mPath);
3978 if (restoreFile == null) {
3979 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
3980 return;
3981 }
3982 File restoreTmpFile = createTempPackageFile();
3983 if (restoreTmpFile == null) {
3984 Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
3985 return;
3986 }
3987 if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
3988 Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
3989 return;
3990 }
3991 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
3992 restoreRes.removedInfo = new PackageRemovedInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 installPackageLI(
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003994 Uri.fromFile(restoreFile),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 isForwardLocked(deletedPackage)
Dianne Hackbornade3eca2009-05-11 18:54:45 -07003996 ? PackageManager.INSTALL_FORWARD_LOCK
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003997 : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
3998 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
3999 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 }
4002 }
4003 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004006 File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 String destFilePath, File destPackageFile, File destResourceFile,
The Android Open Source Project10592532009-03-18 17:39:46 -07004008 PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
Jacek Surazski65e13172009-04-28 15:26:38 +02004009 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 PackageParser.Package newPackage = null;
4011 boolean updatedSettings = false;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004012 int parseFlags = PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 PackageParser.PARSE_IS_SYSTEM;
4014 String packageName = deletedPackage.packageName;
4015 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4016 if (packageName == null) {
4017 Log.w(TAG, "Attempt to delete null packageName.");
4018 return;
4019 }
4020 PackageParser.Package oldPkg;
4021 PackageSetting oldPkgSetting;
4022 synchronized (mPackages) {
4023 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004024 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4026 (oldPkgSetting == null)) {
4027 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4028 return;
4029 }
4030 }
4031 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4032 res.removedInfo.removedPackage = packageName;
4033 // Remove existing system package
4034 removePackageLI(oldPkg, true);
4035 synchronized (mPackages) {
4036 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4037 }
4038
4039 // Successfully disabled the old package. Now proceed with re-installation
4040 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4041 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
4042 newPackage = scanPackageLI(tmpPackageFile, destPackageFile,
4043 destResourceFile, pkg, parseFlags,
4044 SCAN_MONITOR | SCAN_FORCE_DEX
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004045 | SCAN_UPDATE_SIGNATURE
The Android Open Source Project10592532009-03-18 17:39:46 -07004046 | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
4047 | (newInstall ? SCAN_NEW_INSTALL : 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 if (newPackage == null) {
4049 Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
4050 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4051 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4052 }
4053 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004054 updateSettingsLI(packageName, tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 destFilePath, destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004056 destResourceFile, pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 newPackage,
4058 true,
Jacek Surazski65e13172009-04-28 15:26:38 +02004059 forwardLocked,
4060 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 res);
4062 updatedSettings = true;
4063 }
4064
4065 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4066 //update signature on the new package setting
4067 //this should always succeed, since we checked the
4068 //signature earlier.
4069 synchronized(mPackages) {
4070 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4071 parseFlags, true);
4072 }
4073 } else {
4074 // Re installation failed. Restore old information
4075 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004076 if (newPackage != null) {
4077 removePackageLI(newPackage, true);
4078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 // Add back the old system package
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004080 scanPackageLI(oldPkgSetting.codePath, oldPkgSetting.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 oldPkgSetting.resourcePath,
4082 oldPkg, parseFlags,
4083 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004084 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085 // Restore the old system information in Settings
4086 synchronized(mPackages) {
4087 if(updatedSettings) {
4088 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004089 mSettings.setInstallerPackageName(packageName,
4090 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 }
4092 mSettings.writeLP();
4093 }
4094 }
4095 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004096
4097 private void updateSettingsLI(String pkgName, File tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 String destFilePath, File destPackageFile,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004099 File destResourceFile,
4100 PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 PackageParser.Package newPackage,
4102 boolean replacingExistingPackage,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004103 boolean forwardLocked,
Jacek Surazski65e13172009-04-28 15:26:38 +02004104 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 synchronized (mPackages) {
4106 //write settings. the installStatus will be incomplete at this stage.
4107 //note that the new package setting would have already been
4108 //added to mPackages. It hasn't been persisted yet.
4109 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4110 mSettings.writeLP();
4111 }
4112
4113 int retCode = 0;
4114 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4115 retCode = mInstaller.movedex(tmpPackageFile.toString(),
4116 destPackageFile.toString());
4117 if (retCode != 0) {
4118 Log.e(TAG, "Couldn't rename dex file: " + destPackageFile);
4119 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4120 return;
4121 }
4122 }
4123 // XXX There are probably some big issues here: upon doing
4124 // the rename, we have reached the point of no return (the
4125 // original .apk is gone!), so we can't fail. Yet... we can.
4126 if (!tmpPackageFile.renameTo(destPackageFile)) {
4127 Log.e(TAG, "Couldn't move package file to: " + destPackageFile);
4128 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4129 } else {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004130 res.returnCode = setPermissionsLI(pkgName, newPackage, destFilePath,
4131 destResourceFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 forwardLocked);
4133 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4134 return;
4135 } else {
4136 Log.d(TAG, "New package installed in " + destPackageFile);
4137 }
4138 }
4139 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4140 if (mInstaller != null) {
4141 mInstaller.rmdex(tmpPackageFile.getPath());
4142 }
4143 }
4144
4145 synchronized (mPackages) {
4146 grantPermissionsLP(newPackage, true);
4147 res.name = pkgName;
4148 res.uid = newPackage.applicationInfo.uid;
4149 res.pkg = newPackage;
4150 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004151 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004152 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4153 //to update install status
4154 mSettings.writeLP();
4155 }
4156 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004157
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004158 private File getFwdLockedResource(String pkgName) {
4159 final String publicZipFileName = pkgName + ".zip";
4160 return new File(mAppInstallDir, publicZipFileName);
4161 }
4162
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004163 private File copyTempInstallFile(Uri pPackageURI,
4164 PackageInstalledInfo res) {
4165 File tmpPackageFile = createTempPackageFile();
4166 int retCode = PackageManager.INSTALL_SUCCEEDED;
4167 if (tmpPackageFile == null) {
4168 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4169 return null;
4170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004172 if (pPackageURI.getScheme().equals("file")) {
4173 final File srcPackageFile = new File(pPackageURI.getPath());
4174 // We copy the source package file to a temp file and then rename it to the
4175 // destination file in order to eliminate a window where the package directory
4176 // scanner notices the new package file but it's not completely copied yet.
4177 if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
4178 Log.e(TAG, "Couldn't copy package file to temp file.");
4179 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004181 } else if (pPackageURI.getScheme().equals("content")) {
4182 ParcelFileDescriptor fd = null;
4183 try {
4184 fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
4185 } catch (FileNotFoundException e) {
4186 Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
4187 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4188 }
4189 if (fd == null) {
4190 Log.e(TAG, "Couldn't open file descriptor from download service (null).");
4191 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4192 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 if (Config.LOGV) {
4194 Log.v(TAG, "Opened file descriptor from download service.");
4195 }
4196 ParcelFileDescriptor.AutoCloseInputStream
4197 dlStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
4198 // We copy the source package file to a temp file and then rename it to the
4199 // destination file in order to eliminate a window where the package directory
4200 // scanner notices the new package file but it's not completely copied yet.
4201 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
4202 Log.e(TAG, "Couldn't copy package stream to temp file.");
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004203 retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004206 } else {
4207 Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
4208 retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
4209 }
4210
4211 res.returnCode = retCode;
4212 if (retCode != PackageManager.INSTALL_SUCCEEDED) {
4213 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4214 tmpPackageFile.delete();
4215 }
4216 return null;
4217 }
4218 return tmpPackageFile;
4219 }
4220
4221 private void installPackageLI(Uri pPackageURI,
4222 int pFlags, boolean newInstall, String installerPackageName,
4223 File tmpPackageFile, PackageInstalledInfo res) {
4224 String pkgName = null;
4225 boolean forwardLocked = false;
4226 boolean replacingExistingPackage = false;
4227 // Result object to be returned
4228 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4229
4230 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004231 pkgName = PackageParser.parsePackageName(
4232 tmpPackageFile.getAbsolutePath(), 0);
4233 if (pkgName == null) {
4234 Log.e(TAG, "Couldn't find a package name in : " + tmpPackageFile);
4235 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4236 break main_flow;
4237 }
4238 res.name = pkgName;
4239 //initialize some variables before installing pkg
4240 final String pkgFileName = pkgName + ".apk";
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004241 final File destDir = ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 ? mDrmAppPrivateInstallDir
4243 : mAppInstallDir;
4244 final File destPackageFile = new File(destDir, pkgFileName);
4245 final String destFilePath = destPackageFile.getAbsolutePath();
4246 File destResourceFile;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004247 if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07004248 destResourceFile = getFwdLockedResource(pkgName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004249 forwardLocked = true;
4250 } else {
4251 destResourceFile = destPackageFile;
4252 }
4253 // Retrieve PackageSettings and parse package
4254 int parseFlags = PackageParser.PARSE_CHATTY;
4255 parseFlags |= mDefParseFlags;
4256 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4257 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004258 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
4259 destPackageFile.getAbsolutePath(), mMetrics, parseFlags);
4260 if (pkg == null) {
4261 res.returnCode = pp.getParseError();
4262 break main_flow;
4263 }
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004264 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4265 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4266 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4267 break main_flow;
4268 }
4269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004270 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4271 res.returnCode = pp.getParseError();
4272 break main_flow;
4273 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004275 synchronized (mPackages) {
4276 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004277 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004278 && mPackages.containsKey(pkgName)) {
4279 replacingExistingPackage = true;
4280 }
4281 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 if(replacingExistingPackage) {
4284 replacePackageLI(pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004285 tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004287 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004288 res);
4289 } else {
4290 installNewPackageLI(pkgName,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004291 tmpPackageFile,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 destFilePath, destPackageFile, destResourceFile,
Jacek Surazski65e13172009-04-28 15:26:38 +02004293 pkg, forwardLocked, newInstall, installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 res);
4295 }
4296 } finally {
4297 if (tmpPackageFile != null && tmpPackageFile.exists()) {
4298 tmpPackageFile.delete();
4299 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300 }
4301 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 private int setPermissionsLI(String pkgName,
4304 PackageParser.Package newPackage,
4305 String destFilePath,
4306 File destResourceFile,
4307 boolean forwardLocked) {
4308 int retCode;
4309 if (forwardLocked) {
4310 try {
4311 extractPublicFiles(newPackage, destResourceFile);
4312 } catch (IOException e) {
4313 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4314 " forward-locked app.");
4315 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4316 } finally {
4317 //TODO clean up the extracted public files
4318 }
4319 if (mInstaller != null) {
4320 retCode = mInstaller.setForwardLockPerm(pkgName,
4321 newPackage.applicationInfo.uid);
4322 } else {
4323 final int filePermissions =
4324 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
4325 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1,
4326 newPackage.applicationInfo.uid);
4327 }
4328 } else {
4329 final int filePermissions =
4330 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4331 |FileUtils.S_IROTH;
4332 retCode = FileUtils.setPermissions(destFilePath, filePermissions, -1, -1);
4333 }
4334 if (retCode != 0) {
4335 Log.e(TAG, "Couldn't set new package file permissions for " + destFilePath
4336 + ". The return code was: " + retCode);
4337 }
4338 return PackageManager.INSTALL_SUCCEEDED;
4339 }
4340
4341 private boolean isForwardLocked(PackageParser.Package deletedPackage) {
4342 final ApplicationInfo applicationInfo = deletedPackage.applicationInfo;
4343 return applicationInfo.sourceDir.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath());
4344 }
4345
4346 private void extractPublicFiles(PackageParser.Package newPackage,
4347 File publicZipFile) throws IOException {
4348 final ZipOutputStream publicZipOutStream =
4349 new ZipOutputStream(new FileOutputStream(publicZipFile));
4350 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4351
4352 // Copy manifest, resources.arsc and res directory to public zip
4353
4354 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4355 while (privateZipEntries.hasMoreElements()) {
4356 final ZipEntry zipEntry = privateZipEntries.nextElement();
4357 final String zipEntryName = zipEntry.getName();
4358 if ("AndroidManifest.xml".equals(zipEntryName)
4359 || "resources.arsc".equals(zipEntryName)
4360 || zipEntryName.startsWith("res/")) {
4361 try {
4362 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4363 } catch (IOException e) {
4364 try {
4365 publicZipOutStream.close();
4366 throw e;
4367 } finally {
4368 publicZipFile.delete();
4369 }
4370 }
4371 }
4372 }
4373
4374 publicZipOutStream.close();
4375 FileUtils.setPermissions(
4376 publicZipFile.getAbsolutePath(),
4377 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4378 -1, -1);
4379 }
4380
4381 private static void copyZipEntry(ZipEntry zipEntry,
4382 ZipFile inZipFile,
4383 ZipOutputStream outZipStream) throws IOException {
4384 byte[] buffer = new byte[4096];
4385 int num;
4386
4387 ZipEntry newEntry;
4388 if (zipEntry.getMethod() == ZipEntry.STORED) {
4389 // Preserve the STORED method of the input entry.
4390 newEntry = new ZipEntry(zipEntry);
4391 } else {
4392 // Create a new entry so that the compressed len is recomputed.
4393 newEntry = new ZipEntry(zipEntry.getName());
4394 }
4395 outZipStream.putNextEntry(newEntry);
4396
4397 InputStream data = inZipFile.getInputStream(zipEntry);
4398 while ((num = data.read(buffer)) > 0) {
4399 outZipStream.write(buffer, 0, num);
4400 }
4401 outZipStream.flush();
4402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 private void deleteTempPackageFiles() {
4405 FilenameFilter filter = new FilenameFilter() {
4406 public boolean accept(File dir, String name) {
4407 return name.startsWith("vmdl") && name.endsWith(".tmp");
4408 }
4409 };
4410 String tmpFilesList[] = mAppInstallDir.list(filter);
4411 if(tmpFilesList == null) {
4412 return;
4413 }
4414 for(int i = 0; i < tmpFilesList.length; i++) {
4415 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4416 tmpFile.delete();
4417 }
4418 }
4419
4420 private File createTempPackageFile() {
4421 File tmpPackageFile;
4422 try {
4423 tmpPackageFile = File.createTempFile("vmdl", ".tmp", mAppInstallDir);
4424 } catch (IOException e) {
4425 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4426 return null;
4427 }
4428 try {
4429 FileUtils.setPermissions(
4430 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4431 -1, -1);
4432 } catch (IOException e) {
4433 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4434 return null;
4435 }
4436 return tmpPackageFile;
4437 }
4438
4439 public void deletePackage(final String packageName,
4440 final IPackageDeleteObserver observer,
4441 final int flags) {
4442 mContext.enforceCallingOrSelfPermission(
4443 android.Manifest.permission.DELETE_PACKAGES, null);
4444 // Queue up an async operation since the package deletion may take a little while.
4445 mHandler.post(new Runnable() {
4446 public void run() {
4447 mHandler.removeCallbacks(this);
4448 final boolean succeded = deletePackageX(packageName, true, true, flags);
4449 if (observer != null) {
4450 try {
4451 observer.packageDeleted(succeded);
4452 } catch (RemoteException e) {
4453 Log.i(TAG, "Observer no longer exists.");
4454 } //end catch
4455 } //end if
4456 } //end run
4457 });
4458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 /**
4461 * This method is an internal method that could be get invoked either
4462 * to delete an installed package or to clean up a failed installation.
4463 * After deleting an installed package, a broadcast is sent to notify any
4464 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004465 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 * installation wouldn't have sent the initial broadcast either
4467 * The key steps in deleting a package are
4468 * deleting the package information in internal structures like mPackages,
4469 * deleting the packages base directories through installd
4470 * updating mSettings to reflect current status
4471 * persisting settings for later use
4472 * sending a broadcast if necessary
4473 */
4474
4475 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4476 boolean deleteCodeAndResources, int flags) {
4477 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004478 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479
4480 synchronized (mInstallLock) {
4481 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4482 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004485 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4486 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4487
4488 // If the removed package was a system update, the old system packaged
4489 // was re-enabled; we need to broadcast this information
4490 if (systemUpdate) {
4491 Bundle extras = new Bundle(1);
4492 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4493 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4494
4495 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4496 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 }
4499 return res;
4500 }
4501
4502 static class PackageRemovedInfo {
4503 String removedPackage;
4504 int uid = -1;
4505 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004506 boolean isRemovedPackageSystemUpdate = false;
4507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 void sendBroadcast(boolean fullRemove, boolean replacing) {
4509 Bundle extras = new Bundle(1);
4510 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4511 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4512 if (replacing) {
4513 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4514 }
4515 if (removedPackage != null) {
4516 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4517 }
4518 if (removedUid >= 0) {
4519 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
4520 }
4521 }
4522 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 /*
4525 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
4526 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004527 * 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 -08004528 * delete a partially installed application.
4529 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004530 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004531 int flags) {
4532 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004533 if (outInfo != null) {
4534 outInfo.removedPackage = packageName;
4535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 removePackageLI(p, true);
4537 // Retrieve object to delete permissions for shared user later on
4538 PackageSetting deletedPs;
4539 synchronized (mPackages) {
4540 deletedPs = mSettings.mPackages.get(packageName);
4541 }
4542 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
4543 if (mInstaller != null) {
4544 int retCode = mInstaller.remove(packageName);
4545 if (retCode < 0) {
4546 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
4547 + packageName + ", retcode=" + retCode);
4548 // we don't consider this to be a failure of the core package deletion
4549 }
4550 } else {
4551 //for emulator
4552 PackageParser.Package pkg = mPackages.get(packageName);
4553 File dataDir = new File(pkg.applicationInfo.dataDir);
4554 dataDir.delete();
4555 }
4556 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004557 if (outInfo != null) {
4558 outInfo.removedUid = mSettings.removePackageLP(packageName);
4559 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004560 }
4561 }
4562 synchronized (mPackages) {
4563 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
4564 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07004565 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004566 }
4567 // Save settings now
4568 mSettings.writeLP ();
4569 }
4570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 /*
4573 * Tries to delete system package.
4574 */
4575 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004576 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004577 ApplicationInfo applicationInfo = p.applicationInfo;
4578 //applicable for non-partially installed applications only
4579 if (applicationInfo == null) {
4580 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4581 return false;
4582 }
4583 PackageSetting ps = null;
4584 // Confirm if the system package has been updated
4585 // An updated system app can be deleted. This will also have to restore
4586 // the system pkg from system partition
4587 synchronized (mPackages) {
4588 ps = mSettings.getDisabledSystemPkg(p.packageName);
4589 }
4590 if (ps == null) {
4591 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
4592 return false;
4593 } else {
4594 Log.i(TAG, "Deleting system pkg from data partition");
4595 }
4596 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07004597 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004598 boolean deleteCodeAndResources = false;
4599 if (ps.versionCode < p.mVersionCode) {
4600 // Delete code and resources for downgrades
4601 deleteCodeAndResources = true;
4602 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4603 flags &= ~PackageManager.DONT_DELETE_DATA;
4604 }
4605 } else {
4606 // Preserve data by setting flag
4607 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
4608 flags |= PackageManager.DONT_DELETE_DATA;
4609 }
4610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
4612 if (!ret) {
4613 return false;
4614 }
4615 synchronized (mPackages) {
4616 // Reinstate the old system package
4617 mSettings.enableSystemPackageLP(p.packageName);
4618 }
4619 // Install the system package
4620 PackageParser.Package newPkg = scanPackageLI(ps.codePath, ps.codePath, ps.resourcePath,
4621 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
4622 SCAN_MONITOR);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 if (newPkg == null) {
4625 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
4626 return false;
4627 }
4628 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07004629 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630 mSettings.writeLP();
4631 }
4632 return true;
4633 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004634
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004635 private void deletePackageResourcesLI(String packageName,
4636 String sourceDir, String publicSourceDir) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004637 if (sourceDir != null) {
4638 File sourceFile = new File(sourceDir);
4639 if (!sourceFile.exists()) {
4640 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4641 }
4642 // Delete application's code and resources
4643 sourceFile.delete();
4644 if (mInstaller != null) {
4645 int retCode = mInstaller.rmdex(sourceFile.toString());
4646 if (retCode < 0) {
4647 Log.w(TAG, "Couldn't remove dex file for package: "
4648 + packageName + " at location "
4649 + sourceFile.toString() + ", retcode=" + retCode);
4650 // we don't consider this to be a failure of the core package deletion
4651 }
4652 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004653 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07004654 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4655 final File publicSourceFile = new File(publicSourceDir);
4656 if (!publicSourceFile.exists()) {
4657 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4658 }
4659 if (publicSourceFile.exists()) {
4660 publicSourceFile.delete();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004661 }
4662 }
4663 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 private boolean deleteInstalledPackageLI(PackageParser.Package p,
4666 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4667 ApplicationInfo applicationInfo = p.applicationInfo;
4668 if (applicationInfo == null) {
4669 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4670 return false;
4671 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07004672 if (outInfo != null) {
4673 outInfo.uid = applicationInfo.uid;
4674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004675
4676 // Delete package data from internal structures and also remove data if flag is set
4677 removePackageDataLI(p, outInfo, flags);
4678
4679 // Delete application code and resources
4680 if (deleteCodeAndResources) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004681 deletePackageResourcesLI(applicationInfo.packageName,
4682 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004683 }
4684 return true;
4685 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 /*
4688 * This method handles package deletion in general
4689 */
4690 private boolean deletePackageLI(String packageName,
4691 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
4692 if (packageName == null) {
4693 Log.w(TAG, "Attempt to delete null packageName.");
4694 return false;
4695 }
4696 PackageParser.Package p;
4697 boolean dataOnly = false;
4698 synchronized (mPackages) {
4699 p = mPackages.get(packageName);
4700 if (p == null) {
4701 //this retrieves partially installed apps
4702 dataOnly = true;
4703 PackageSetting ps = mSettings.mPackages.get(packageName);
4704 if (ps == null) {
4705 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4706 return false;
4707 }
4708 p = ps.pkg;
4709 }
4710 }
4711 if (p == null) {
4712 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4713 return false;
4714 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 if (dataOnly) {
4717 // Delete application data first
4718 removePackageDataLI(p, outInfo, flags);
4719 return true;
4720 }
4721 // At this point the package should have ApplicationInfo associated with it
4722 if (p.applicationInfo == null) {
4723 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
4724 return false;
4725 }
4726 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4727 Log.i(TAG, "Removing system package:"+p.packageName);
4728 // When an updated system application is deleted we delete the existing resources as well and
4729 // fall back to existing code in system partition
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004730 return deleteSystemPackageLI(p, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 }
4732 Log.i(TAG, "Removing non-system package:"+p.packageName);
4733 return deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
4734 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004736 public void clearApplicationUserData(final String packageName,
4737 final IPackageDataObserver observer) {
4738 mContext.enforceCallingOrSelfPermission(
4739 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
4740 // Queue up an async operation since the package deletion may take a little while.
4741 mHandler.post(new Runnable() {
4742 public void run() {
4743 mHandler.removeCallbacks(this);
4744 final boolean succeeded;
4745 synchronized (mInstallLock) {
4746 succeeded = clearApplicationUserDataLI(packageName);
4747 }
4748 if (succeeded) {
4749 // invoke DeviceStorageMonitor's update method to clear any notifications
4750 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
4751 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
4752 if (dsm != null) {
4753 dsm.updateMemory();
4754 }
4755 }
4756 if(observer != null) {
4757 try {
4758 observer.onRemoveCompleted(packageName, succeeded);
4759 } catch (RemoteException e) {
4760 Log.i(TAG, "Observer no longer exists.");
4761 }
4762 } //end if observer
4763 } //end run
4764 });
4765 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 private boolean clearApplicationUserDataLI(String packageName) {
4768 if (packageName == null) {
4769 Log.w(TAG, "Attempt to delete null packageName.");
4770 return false;
4771 }
4772 PackageParser.Package p;
4773 boolean dataOnly = false;
4774 synchronized (mPackages) {
4775 p = mPackages.get(packageName);
4776 if(p == null) {
4777 dataOnly = true;
4778 PackageSetting ps = mSettings.mPackages.get(packageName);
4779 if((ps == null) || (ps.pkg == null)) {
4780 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4781 return false;
4782 }
4783 p = ps.pkg;
4784 }
4785 }
4786 if(!dataOnly) {
4787 //need to check this only for fully installed applications
4788 if (p == null) {
4789 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4790 return false;
4791 }
4792 final ApplicationInfo applicationInfo = p.applicationInfo;
4793 if (applicationInfo == null) {
4794 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4795 return false;
4796 }
4797 }
4798 if (mInstaller != null) {
4799 int retCode = mInstaller.clearUserData(packageName);
4800 if (retCode < 0) {
4801 Log.w(TAG, "Couldn't remove cache files for package: "
4802 + packageName);
4803 return false;
4804 }
4805 }
4806 return true;
4807 }
4808
4809 public void deleteApplicationCacheFiles(final String packageName,
4810 final IPackageDataObserver observer) {
4811 mContext.enforceCallingOrSelfPermission(
4812 android.Manifest.permission.DELETE_CACHE_FILES, null);
4813 // Queue up an async operation since the package deletion may take a little while.
4814 mHandler.post(new Runnable() {
4815 public void run() {
4816 mHandler.removeCallbacks(this);
4817 final boolean succeded;
4818 synchronized (mInstallLock) {
4819 succeded = deleteApplicationCacheFilesLI(packageName);
4820 }
4821 if(observer != null) {
4822 try {
4823 observer.onRemoveCompleted(packageName, succeded);
4824 } catch (RemoteException e) {
4825 Log.i(TAG, "Observer no longer exists.");
4826 }
4827 } //end if observer
4828 } //end run
4829 });
4830 }
4831
4832 private boolean deleteApplicationCacheFilesLI(String packageName) {
4833 if (packageName == null) {
4834 Log.w(TAG, "Attempt to delete null packageName.");
4835 return false;
4836 }
4837 PackageParser.Package p;
4838 synchronized (mPackages) {
4839 p = mPackages.get(packageName);
4840 }
4841 if (p == null) {
4842 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4843 return false;
4844 }
4845 final ApplicationInfo applicationInfo = p.applicationInfo;
4846 if (applicationInfo == null) {
4847 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4848 return false;
4849 }
4850 if (mInstaller != null) {
4851 int retCode = mInstaller.deleteCacheFiles(packageName);
4852 if (retCode < 0) {
4853 Log.w(TAG, "Couldn't remove cache files for package: "
4854 + packageName);
4855 return false;
4856 }
4857 }
4858 return true;
4859 }
4860
4861 public void getPackageSizeInfo(final String packageName,
4862 final IPackageStatsObserver observer) {
4863 mContext.enforceCallingOrSelfPermission(
4864 android.Manifest.permission.GET_PACKAGE_SIZE, null);
4865 // Queue up an async operation since the package deletion may take a little while.
4866 mHandler.post(new Runnable() {
4867 public void run() {
4868 mHandler.removeCallbacks(this);
4869 PackageStats lStats = new PackageStats(packageName);
4870 final boolean succeded;
4871 synchronized (mInstallLock) {
4872 succeded = getPackageSizeInfoLI(packageName, lStats);
4873 }
4874 if(observer != null) {
4875 try {
4876 observer.onGetStatsCompleted(lStats, succeded);
4877 } catch (RemoteException e) {
4878 Log.i(TAG, "Observer no longer exists.");
4879 }
4880 } //end if observer
4881 } //end run
4882 });
4883 }
4884
4885 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
4886 if (packageName == null) {
4887 Log.w(TAG, "Attempt to get size of null packageName.");
4888 return false;
4889 }
4890 PackageParser.Package p;
4891 boolean dataOnly = false;
4892 synchronized (mPackages) {
4893 p = mPackages.get(packageName);
4894 if(p == null) {
4895 dataOnly = true;
4896 PackageSetting ps = mSettings.mPackages.get(packageName);
4897 if((ps == null) || (ps.pkg == null)) {
4898 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
4899 return false;
4900 }
4901 p = ps.pkg;
4902 }
4903 }
4904 String publicSrcDir = null;
4905 if(!dataOnly) {
4906 final ApplicationInfo applicationInfo = p.applicationInfo;
4907 if (applicationInfo == null) {
4908 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
4909 return false;
4910 }
4911 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
4912 }
4913 if (mInstaller != null) {
4914 int res = mInstaller.getSizeInfo(packageName, p.mPath,
4915 publicSrcDir, pStats);
4916 if (res < 0) {
4917 return false;
4918 } else {
4919 return true;
4920 }
4921 }
4922 return true;
4923 }
4924
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 public void addPackageToPreferred(String packageName) {
4927 mContext.enforceCallingOrSelfPermission(
4928 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004929 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 }
4931
4932 public void removePackageFromPreferred(String packageName) {
4933 mContext.enforceCallingOrSelfPermission(
4934 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004935 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 }
4937
4938 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08004939 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004940 }
4941
4942 public void addPreferredActivity(IntentFilter filter, int match,
4943 ComponentName[] set, ComponentName activity) {
4944 mContext.enforceCallingOrSelfPermission(
4945 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4946
4947 synchronized (mPackages) {
4948 Log.i(TAG, "Adding preferred activity " + activity + ":");
4949 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4950 mSettings.mPreferredActivities.addFilter(
4951 new PreferredActivity(filter, match, set, activity));
4952 mSettings.writeLP();
4953 }
4954 }
4955
Satish Sampath8dbe6122009-06-02 23:35:54 +01004956 public void replacePreferredActivity(IntentFilter filter, int match,
4957 ComponentName[] set, ComponentName activity) {
4958 mContext.enforceCallingOrSelfPermission(
4959 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4960 if (filter.countActions() != 1) {
4961 throw new IllegalArgumentException(
4962 "replacePreferredActivity expects filter to have only 1 action.");
4963 }
4964 if (filter.countCategories() != 1) {
4965 throw new IllegalArgumentException(
4966 "replacePreferredActivity expects filter to have only 1 category.");
4967 }
4968 if (filter.countDataAuthorities() != 0
4969 || filter.countDataPaths() != 0
4970 || filter.countDataSchemes() != 0
4971 || filter.countDataTypes() != 0) {
4972 throw new IllegalArgumentException(
4973 "replacePreferredActivity expects filter to have no data authorities, " +
4974 "paths, schemes or types.");
4975 }
4976 synchronized (mPackages) {
4977 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
4978 String action = filter.getAction(0);
4979 String category = filter.getCategory(0);
4980 while (it.hasNext()) {
4981 PreferredActivity pa = it.next();
4982 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
4983 it.remove();
4984 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
4985 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
4986 }
4987 }
4988 addPreferredActivity(filter, match, set, activity);
4989 }
4990 }
4991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 public void clearPackagePreferredActivities(String packageName) {
4993 mContext.enforceCallingOrSelfPermission(
4994 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
4995
4996 synchronized (mPackages) {
4997 if (clearPackagePreferredActivitiesLP(packageName)) {
4998 mSettings.writeLP();
4999 }
5000 }
5001 }
5002
5003 boolean clearPackagePreferredActivitiesLP(String packageName) {
5004 boolean changed = false;
5005 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5006 while (it.hasNext()) {
5007 PreferredActivity pa = it.next();
5008 if (pa.mActivity.getPackageName().equals(packageName)) {
5009 it.remove();
5010 changed = true;
5011 }
5012 }
5013 return changed;
5014 }
5015
5016 public int getPreferredActivities(List<IntentFilter> outFilters,
5017 List<ComponentName> outActivities, String packageName) {
5018
5019 int num = 0;
5020 synchronized (mPackages) {
5021 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5022 while (it.hasNext()) {
5023 PreferredActivity pa = it.next();
5024 if (packageName == null
5025 || pa.mActivity.getPackageName().equals(packageName)) {
5026 if (outFilters != null) {
5027 outFilters.add(new IntentFilter(pa));
5028 }
5029 if (outActivities != null) {
5030 outActivities.add(pa.mActivity);
5031 }
5032 }
5033 }
5034 }
5035
5036 return num;
5037 }
5038
5039 public void setApplicationEnabledSetting(String appPackageName,
5040 int newState, int flags) {
5041 setEnabledSetting(appPackageName, null, newState, flags);
5042 }
5043
5044 public void setComponentEnabledSetting(ComponentName componentName,
5045 int newState, int flags) {
5046 setEnabledSetting(componentName.getPackageName(),
5047 componentName.getClassName(), newState, flags);
5048 }
5049
5050 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005051 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5053 || newState == COMPONENT_ENABLED_STATE_ENABLED
5054 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5055 throw new IllegalArgumentException("Invalid new component state: "
5056 + newState);
5057 }
5058 PackageSetting pkgSetting;
5059 final int uid = Binder.getCallingUid();
5060 final int permission = mContext.checkCallingPermission(
5061 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5062 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005063 boolean sendNow = false;
5064 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005065 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005067 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005068 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005069 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005071 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005073 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 }
5075 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005076 "Unknown component: " + packageName
5077 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005078 }
5079 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5080 throw new SecurityException(
5081 "Permission Denial: attempt to change component state from pid="
5082 + Binder.getCallingPid()
5083 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5084 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005085 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005086 // We're dealing with an application/package level state change
5087 pkgSetting.enabled = newState;
5088 } else {
5089 // We're dealing with a component level state change
5090 switch (newState) {
5091 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005092 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 break;
5094 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005095 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005096 break;
5097 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005098 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 break;
5100 default:
5101 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005102 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 }
5104 }
5105 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005106 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005107 components = mPendingBroadcasts.get(packageName);
5108 boolean newPackage = components == null;
5109 if (newPackage) {
5110 components = new ArrayList<String>();
5111 }
5112 if (!components.contains(componentName)) {
5113 components.add(componentName);
5114 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005115 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5116 sendNow = true;
5117 // Purge entry from pending broadcast list if another one exists already
5118 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005119 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005120 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005121 if (newPackage) {
5122 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005123 }
5124 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5125 // Schedule a message
5126 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5127 }
5128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 long callingId = Binder.clearCallingIdentity();
5132 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005133 if (sendNow) {
5134 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005135 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005137 } finally {
5138 Binder.restoreCallingIdentity(callingId);
5139 }
5140 }
5141
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005142 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005143 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5144 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5145 + " components=" + componentNames);
5146 Bundle extras = new Bundle(4);
5147 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5148 String nameList[] = new String[componentNames.size()];
5149 componentNames.toArray(nameList);
5150 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005151 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5152 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005153 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005154 }
5155
Jacek Surazski65e13172009-04-28 15:26:38 +02005156 public String getInstallerPackageName(String packageName) {
5157 synchronized (mPackages) {
5158 PackageSetting pkg = mSettings.mPackages.get(packageName);
5159 if (pkg == null) {
5160 throw new IllegalArgumentException("Unknown package: " + packageName);
5161 }
5162 return pkg.installerPackageName;
5163 }
5164 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005166 public int getApplicationEnabledSetting(String appPackageName) {
5167 synchronized (mPackages) {
5168 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5169 if (pkg == null) {
5170 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5171 }
5172 return pkg.enabled;
5173 }
5174 }
5175
5176 public int getComponentEnabledSetting(ComponentName componentName) {
5177 synchronized (mPackages) {
5178 final String packageNameStr = componentName.getPackageName();
5179 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5180 if (pkg == null) {
5181 throw new IllegalArgumentException("Unknown component: " + componentName);
5182 }
5183 final String classNameStr = componentName.getClassName();
5184 return pkg.currentEnabledStateLP(classNameStr);
5185 }
5186 }
5187
5188 public void enterSafeMode() {
5189 if (!mSystemReady) {
5190 mSafeMode = true;
5191 }
5192 }
5193
5194 public void systemReady() {
5195 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005196
5197 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005198 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005199 mContext.getContentResolver(),
5200 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005201 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005202 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005203 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005204 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 }
5206
5207 public boolean isSafeMode() {
5208 return mSafeMode;
5209 }
5210
5211 public boolean hasSystemUidErrors() {
5212 return mHasSystemUidErrors;
5213 }
5214
5215 static String arrayToString(int[] array) {
5216 StringBuffer buf = new StringBuffer(128);
5217 buf.append('[');
5218 if (array != null) {
5219 for (int i=0; i<array.length; i++) {
5220 if (i > 0) buf.append(", ");
5221 buf.append(array[i]);
5222 }
5223 }
5224 buf.append(']');
5225 return buf.toString();
5226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 @Override
5229 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5230 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5231 != PackageManager.PERMISSION_GRANTED) {
5232 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5233 + Binder.getCallingPid()
5234 + ", uid=" + Binder.getCallingUid()
5235 + " without permission "
5236 + android.Manifest.permission.DUMP);
5237 return;
5238 }
5239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005240 synchronized (mPackages) {
5241 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005242 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 pw.println(" ");
5244 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005245 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 pw.println(" ");
5247 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005248 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 pw.println(" ");
5250 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005251 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005252 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005253 pw.println("Permissions:");
5254 {
5255 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005256 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5257 pw.print(Integer.toHexString(System.identityHashCode(p)));
5258 pw.println("):");
5259 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5260 pw.print(" uid="); pw.print(p.uid);
5261 pw.print(" gids="); pw.print(arrayToString(p.gids));
5262 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 }
5264 }
5265 pw.println(" ");
5266 pw.println("Packages:");
5267 {
5268 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005269 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5270 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5271 pw.println("):");
5272 pw.print(" userId="); pw.print(ps.userId);
5273 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5274 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5275 pw.print(" pkg="); pw.println(ps.pkg);
5276 pw.print(" codePath="); pw.println(ps.codePathString);
5277 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005279 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005280 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005281 pw.print(" supportsScreens=[");
5282 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005283 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005284 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005285 if (!first) pw.print(", ");
5286 first = false;
5287 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005288 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005289 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005290 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005291 if (!first) pw.print(", ");
5292 first = false;
5293 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005294 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005295 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005296 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005297 if (!first) pw.print(", ");
5298 first = false;
5299 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005300 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005301 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005302 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005303 if (!first) pw.print(", ");
5304 first = false;
5305 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005307 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005308 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5309 if (!first) pw.print(", ");
5310 first = false;
5311 pw.print("anyDensity");
5312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005313 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005314 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005315 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5316 pw.print(" signatures="); pw.println(ps.signatures);
5317 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5318 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5319 pw.print(" installStatus="); pw.print(ps.installStatus);
5320 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 if (ps.disabledComponents.size() > 0) {
5322 pw.println(" disabledComponents:");
5323 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005324 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 }
5326 }
5327 if (ps.enabledComponents.size() > 0) {
5328 pw.println(" enabledComponents:");
5329 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005330 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 }
5332 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005333 if (ps.grantedPermissions.size() > 0) {
5334 pw.println(" grantedPermissions:");
5335 for (String s : ps.grantedPermissions) {
5336 pw.print(" "); pw.println(s);
5337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005339 if (ps.loadedPermissions.size() > 0) {
5340 pw.println(" loadedPermissions:");
5341 for (String s : ps.loadedPermissions) {
5342 pw.print(" "); pw.println(s);
5343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 }
5345 }
5346 }
5347 pw.println(" ");
5348 pw.println("Shared Users:");
5349 {
5350 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005351 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5352 pw.print(Integer.toHexString(System.identityHashCode(su)));
5353 pw.println("):");
5354 pw.print(" userId="); pw.print(su.userId);
5355 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005356 pw.println(" grantedPermissions:");
5357 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005358 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 }
5360 pw.println(" loadedPermissions:");
5361 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005362 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005363 }
5364 }
5365 }
5366 pw.println(" ");
5367 pw.println("Settings parse messages:");
5368 pw.println(mSettings.mReadMessages.toString());
5369 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005370
5371 synchronized (mProviders) {
5372 pw.println(" ");
5373 pw.println("Registered ContentProviders:");
5374 for (PackageParser.Provider p : mProviders.values()) {
5375 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5376 pw.println(p.toString());
5377 }
5378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 }
5380
5381 static final class BasePermission {
5382 final static int TYPE_NORMAL = 0;
5383 final static int TYPE_BUILTIN = 1;
5384 final static int TYPE_DYNAMIC = 2;
5385
5386 final String name;
5387 final String sourcePackage;
5388 final int type;
5389 PackageParser.Permission perm;
5390 PermissionInfo pendingInfo;
5391 int uid;
5392 int[] gids;
5393
5394 BasePermission(String _name, String _sourcePackage, int _type) {
5395 name = _name;
5396 sourcePackage = _sourcePackage;
5397 type = _type;
5398 }
5399 }
5400
5401 static class PackageSignatures {
5402 private Signature[] mSignatures;
5403
5404 PackageSignatures(Signature[] sigs) {
5405 assignSignatures(sigs);
5406 }
5407
5408 PackageSignatures() {
5409 }
5410
5411 void writeXml(XmlSerializer serializer, String tagName,
5412 ArrayList<Signature> pastSignatures) throws IOException {
5413 if (mSignatures == null) {
5414 return;
5415 }
5416 serializer.startTag(null, tagName);
5417 serializer.attribute(null, "count",
5418 Integer.toString(mSignatures.length));
5419 for (int i=0; i<mSignatures.length; i++) {
5420 serializer.startTag(null, "cert");
5421 final Signature sig = mSignatures[i];
5422 final int sigHash = sig.hashCode();
5423 final int numPast = pastSignatures.size();
5424 int j;
5425 for (j=0; j<numPast; j++) {
5426 Signature pastSig = pastSignatures.get(j);
5427 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5428 serializer.attribute(null, "index", Integer.toString(j));
5429 break;
5430 }
5431 }
5432 if (j >= numPast) {
5433 pastSignatures.add(sig);
5434 serializer.attribute(null, "index", Integer.toString(numPast));
5435 serializer.attribute(null, "key", sig.toCharsString());
5436 }
5437 serializer.endTag(null, "cert");
5438 }
5439 serializer.endTag(null, tagName);
5440 }
5441
5442 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5443 throws IOException, XmlPullParserException {
5444 String countStr = parser.getAttributeValue(null, "count");
5445 if (countStr == null) {
5446 reportSettingsProblem(Log.WARN,
5447 "Error in package manager settings: <signatures> has"
5448 + " no count at " + parser.getPositionDescription());
5449 XmlUtils.skipCurrentTag(parser);
5450 }
5451 final int count = Integer.parseInt(countStr);
5452 mSignatures = new Signature[count];
5453 int pos = 0;
5454
5455 int outerDepth = parser.getDepth();
5456 int type;
5457 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5458 && (type != XmlPullParser.END_TAG
5459 || parser.getDepth() > outerDepth)) {
5460 if (type == XmlPullParser.END_TAG
5461 || type == XmlPullParser.TEXT) {
5462 continue;
5463 }
5464
5465 String tagName = parser.getName();
5466 if (tagName.equals("cert")) {
5467 if (pos < count) {
5468 String index = parser.getAttributeValue(null, "index");
5469 if (index != null) {
5470 try {
5471 int idx = Integer.parseInt(index);
5472 String key = parser.getAttributeValue(null, "key");
5473 if (key == null) {
5474 if (idx >= 0 && idx < pastSignatures.size()) {
5475 Signature sig = pastSignatures.get(idx);
5476 if (sig != null) {
5477 mSignatures[pos] = pastSignatures.get(idx);
5478 pos++;
5479 } else {
5480 reportSettingsProblem(Log.WARN,
5481 "Error in package manager settings: <cert> "
5482 + "index " + index + " is not defined at "
5483 + parser.getPositionDescription());
5484 }
5485 } else {
5486 reportSettingsProblem(Log.WARN,
5487 "Error in package manager settings: <cert> "
5488 + "index " + index + " is out of bounds at "
5489 + parser.getPositionDescription());
5490 }
5491 } else {
5492 while (pastSignatures.size() <= idx) {
5493 pastSignatures.add(null);
5494 }
5495 Signature sig = new Signature(key);
5496 pastSignatures.set(idx, sig);
5497 mSignatures[pos] = sig;
5498 pos++;
5499 }
5500 } catch (NumberFormatException e) {
5501 reportSettingsProblem(Log.WARN,
5502 "Error in package manager settings: <cert> "
5503 + "index " + index + " is not a number at "
5504 + parser.getPositionDescription());
5505 }
5506 } else {
5507 reportSettingsProblem(Log.WARN,
5508 "Error in package manager settings: <cert> has"
5509 + " no index at " + parser.getPositionDescription());
5510 }
5511 } else {
5512 reportSettingsProblem(Log.WARN,
5513 "Error in package manager settings: too "
5514 + "many <cert> tags, expected " + count
5515 + " at " + parser.getPositionDescription());
5516 }
5517 } else {
5518 reportSettingsProblem(Log.WARN,
5519 "Unknown element under <cert>: "
5520 + parser.getName());
5521 }
5522 XmlUtils.skipCurrentTag(parser);
5523 }
5524
5525 if (pos < count) {
5526 // Should never happen -- there is an error in the written
5527 // settings -- but if it does we don't want to generate
5528 // a bad array.
5529 Signature[] newSigs = new Signature[pos];
5530 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5531 mSignatures = newSigs;
5532 }
5533 }
5534
5535 /**
5536 * If any of the given 'sigs' is contained in the existing signatures,
5537 * then completely replace the current signatures with the ones in
5538 * 'sigs'. This is used for updating an existing package to a newly
5539 * installed version.
5540 */
5541 boolean updateSignatures(Signature[] sigs, boolean update) {
5542 if (mSignatures == null) {
5543 if (update) {
5544 assignSignatures(sigs);
5545 }
5546 return true;
5547 }
5548 if (sigs == null) {
5549 return false;
5550 }
5551
5552 for (int i=0; i<sigs.length; i++) {
5553 Signature sig = sigs[i];
5554 for (int j=0; j<mSignatures.length; j++) {
5555 if (mSignatures[j].equals(sig)) {
5556 if (update) {
5557 assignSignatures(sigs);
5558 }
5559 return true;
5560 }
5561 }
5562 }
5563 return false;
5564 }
5565
5566 /**
5567 * If any of the given 'sigs' is contained in the existing signatures,
5568 * then add in any new signatures found in 'sigs'. This is used for
5569 * including a new package into an existing shared user id.
5570 */
5571 boolean mergeSignatures(Signature[] sigs, boolean update) {
5572 if (mSignatures == null) {
5573 if (update) {
5574 assignSignatures(sigs);
5575 }
5576 return true;
5577 }
5578 if (sigs == null) {
5579 return false;
5580 }
5581
5582 Signature[] added = null;
5583 int addedCount = 0;
5584 boolean haveMatch = false;
5585 for (int i=0; i<sigs.length; i++) {
5586 Signature sig = sigs[i];
5587 boolean found = false;
5588 for (int j=0; j<mSignatures.length; j++) {
5589 if (mSignatures[j].equals(sig)) {
5590 found = true;
5591 haveMatch = true;
5592 break;
5593 }
5594 }
5595
5596 if (!found) {
5597 if (added == null) {
5598 added = new Signature[sigs.length];
5599 }
5600 added[i] = sig;
5601 addedCount++;
5602 }
5603 }
5604
5605 if (!haveMatch) {
5606 // Nothing matched -- reject the new signatures.
5607 return false;
5608 }
5609 if (added == null) {
5610 // Completely matched -- nothing else to do.
5611 return true;
5612 }
5613
5614 // Add additional signatures in.
5615 if (update) {
5616 Signature[] total = new Signature[addedCount+mSignatures.length];
5617 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
5618 int j = mSignatures.length;
5619 for (int i=0; i<added.length; i++) {
5620 if (added[i] != null) {
5621 total[j] = added[i];
5622 j++;
5623 }
5624 }
5625 mSignatures = total;
5626 }
5627 return true;
5628 }
5629
5630 private void assignSignatures(Signature[] sigs) {
5631 if (sigs == null) {
5632 mSignatures = null;
5633 return;
5634 }
5635 mSignatures = new Signature[sigs.length];
5636 for (int i=0; i<sigs.length; i++) {
5637 mSignatures[i] = sigs[i];
5638 }
5639 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 @Override
5642 public String toString() {
5643 StringBuffer buf = new StringBuffer(128);
5644 buf.append("PackageSignatures{");
5645 buf.append(Integer.toHexString(System.identityHashCode(this)));
5646 buf.append(" [");
5647 if (mSignatures != null) {
5648 for (int i=0; i<mSignatures.length; i++) {
5649 if (i > 0) buf.append(", ");
5650 buf.append(Integer.toHexString(
5651 System.identityHashCode(mSignatures[i])));
5652 }
5653 }
5654 buf.append("]}");
5655 return buf.toString();
5656 }
5657 }
5658
5659 static class PreferredActivity extends IntentFilter {
5660 final int mMatch;
5661 final String[] mSetPackages;
5662 final String[] mSetClasses;
5663 final String[] mSetComponents;
5664 final ComponentName mActivity;
5665 final String mShortActivity;
5666 String mParseError;
5667
5668 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
5669 ComponentName activity) {
5670 super(filter);
5671 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
5672 mActivity = activity;
5673 mShortActivity = activity.flattenToShortString();
5674 mParseError = null;
5675 if (set != null) {
5676 final int N = set.length;
5677 String[] myPackages = new String[N];
5678 String[] myClasses = new String[N];
5679 String[] myComponents = new String[N];
5680 for (int i=0; i<N; i++) {
5681 ComponentName cn = set[i];
5682 if (cn == null) {
5683 mSetPackages = null;
5684 mSetClasses = null;
5685 mSetComponents = null;
5686 return;
5687 }
5688 myPackages[i] = cn.getPackageName().intern();
5689 myClasses[i] = cn.getClassName().intern();
5690 myComponents[i] = cn.flattenToShortString().intern();
5691 }
5692 mSetPackages = myPackages;
5693 mSetClasses = myClasses;
5694 mSetComponents = myComponents;
5695 } else {
5696 mSetPackages = null;
5697 mSetClasses = null;
5698 mSetComponents = null;
5699 }
5700 }
5701
5702 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
5703 IOException {
5704 mShortActivity = parser.getAttributeValue(null, "name");
5705 mActivity = ComponentName.unflattenFromString(mShortActivity);
5706 if (mActivity == null) {
5707 mParseError = "Bad activity name " + mShortActivity;
5708 }
5709 String matchStr = parser.getAttributeValue(null, "match");
5710 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
5711 String setCountStr = parser.getAttributeValue(null, "set");
5712 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
5713
5714 String[] myPackages = setCount > 0 ? new String[setCount] : null;
5715 String[] myClasses = setCount > 0 ? new String[setCount] : null;
5716 String[] myComponents = setCount > 0 ? new String[setCount] : null;
5717
5718 int setPos = 0;
5719
5720 int outerDepth = parser.getDepth();
5721 int type;
5722 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5723 && (type != XmlPullParser.END_TAG
5724 || parser.getDepth() > outerDepth)) {
5725 if (type == XmlPullParser.END_TAG
5726 || type == XmlPullParser.TEXT) {
5727 continue;
5728 }
5729
5730 String tagName = parser.getName();
5731 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
5732 // + parser.getDepth() + " tag=" + tagName);
5733 if (tagName.equals("set")) {
5734 String name = parser.getAttributeValue(null, "name");
5735 if (name == null) {
5736 if (mParseError == null) {
5737 mParseError = "No name in set tag in preferred activity "
5738 + mShortActivity;
5739 }
5740 } else if (setPos >= setCount) {
5741 if (mParseError == null) {
5742 mParseError = "Too many set tags in preferred activity "
5743 + mShortActivity;
5744 }
5745 } else {
5746 ComponentName cn = ComponentName.unflattenFromString(name);
5747 if (cn == null) {
5748 if (mParseError == null) {
5749 mParseError = "Bad set name " + name + " in preferred activity "
5750 + mShortActivity;
5751 }
5752 } else {
5753 myPackages[setPos] = cn.getPackageName();
5754 myClasses[setPos] = cn.getClassName();
5755 myComponents[setPos] = name;
5756 setPos++;
5757 }
5758 }
5759 XmlUtils.skipCurrentTag(parser);
5760 } else if (tagName.equals("filter")) {
5761 //Log.i(TAG, "Starting to parse filter...");
5762 readFromXml(parser);
5763 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
5764 // + parser.getDepth() + " tag=" + parser.getName());
5765 } else {
5766 reportSettingsProblem(Log.WARN,
5767 "Unknown element under <preferred-activities>: "
5768 + parser.getName());
5769 XmlUtils.skipCurrentTag(parser);
5770 }
5771 }
5772
5773 if (setPos != setCount) {
5774 if (mParseError == null) {
5775 mParseError = "Not enough set tags (expected " + setCount
5776 + " but found " + setPos + ") in " + mShortActivity;
5777 }
5778 }
5779
5780 mSetPackages = myPackages;
5781 mSetClasses = myClasses;
5782 mSetComponents = myComponents;
5783 }
5784
5785 public void writeToXml(XmlSerializer serializer) throws IOException {
5786 final int NS = mSetClasses != null ? mSetClasses.length : 0;
5787 serializer.attribute(null, "name", mShortActivity);
5788 serializer.attribute(null, "match", Integer.toHexString(mMatch));
5789 serializer.attribute(null, "set", Integer.toString(NS));
5790 for (int s=0; s<NS; s++) {
5791 serializer.startTag(null, "set");
5792 serializer.attribute(null, "name", mSetComponents[s]);
5793 serializer.endTag(null, "set");
5794 }
5795 serializer.startTag(null, "filter");
5796 super.writeToXml(serializer);
5797 serializer.endTag(null, "filter");
5798 }
5799
5800 boolean sameSet(List<ResolveInfo> query, int priority) {
5801 if (mSetPackages == null) return false;
5802 final int NQ = query.size();
5803 final int NS = mSetPackages.length;
5804 int numMatch = 0;
5805 for (int i=0; i<NQ; i++) {
5806 ResolveInfo ri = query.get(i);
5807 if (ri.priority != priority) continue;
5808 ActivityInfo ai = ri.activityInfo;
5809 boolean good = false;
5810 for (int j=0; j<NS; j++) {
5811 if (mSetPackages[j].equals(ai.packageName)
5812 && mSetClasses[j].equals(ai.name)) {
5813 numMatch++;
5814 good = true;
5815 break;
5816 }
5817 }
5818 if (!good) return false;
5819 }
5820 return numMatch == NS;
5821 }
5822 }
5823
5824 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07005825 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005827 HashSet<String> grantedPermissions = new HashSet<String>();
5828 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005832 GrantedPermissions(int pkgFlags) {
5833 this.pkgFlags = pkgFlags & ApplicationInfo.FLAG_SYSTEM;
5834 }
5835 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 /**
5838 * Settings base class for pending and resolved classes.
5839 */
5840 static class PackageSettingBase extends GrantedPermissions {
5841 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07005842 File codePath;
5843 String codePathString;
5844 File resourcePath;
5845 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005846 private long timeStamp;
5847 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005848 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849
5850 PackageSignatures signatures = new PackageSignatures();
5851
5852 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005854 /* Explicitly disabled components */
5855 HashSet<String> disabledComponents = new HashSet<String>(0);
5856 /* Explicitly enabled components */
5857 HashSet<String> enabledComponents = new HashSet<String>(0);
5858 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
5859 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005860
Jacek Surazski65e13172009-04-28 15:26:38 +02005861 /* package name of the app that installed this package */
5862 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863
5864 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005865 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005866 super(pkgFlags);
5867 this.name = name;
5868 this.codePath = codePath;
5869 this.codePathString = codePath.toString();
5870 this.resourcePath = resourcePath;
5871 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005872 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 }
5874
Jacek Surazski65e13172009-04-28 15:26:38 +02005875 public void setInstallerPackageName(String packageName) {
5876 installerPackageName = packageName;
5877 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005878
Jacek Surazski65e13172009-04-28 15:26:38 +02005879 String getInstallerPackageName() {
5880 return installerPackageName;
5881 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 public void setInstallStatus(int newStatus) {
5884 installStatus = newStatus;
5885 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 public int getInstallStatus() {
5888 return installStatus;
5889 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005891 public void setTimeStamp(long newStamp) {
5892 if (newStamp != timeStamp) {
5893 timeStamp = newStamp;
5894 timeStampString = Long.toString(newStamp);
5895 }
5896 }
5897
5898 public void setTimeStamp(long newStamp, String newStampStr) {
5899 timeStamp = newStamp;
5900 timeStampString = newStampStr;
5901 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 public long getTimeStamp() {
5904 return timeStamp;
5905 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 public String getTimeStampStr() {
5908 return timeStampString;
5909 }
5910
5911 public void copyFrom(PackageSettingBase base) {
5912 grantedPermissions = base.grantedPermissions;
5913 gids = base.gids;
5914 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 timeStamp = base.timeStamp;
5917 timeStampString = base.timeStampString;
5918 signatures = base.signatures;
5919 permissionsFixed = base.permissionsFixed;
5920 disabledComponents = base.disabledComponents;
5921 enabledComponents = base.enabledComponents;
5922 enabled = base.enabled;
5923 installStatus = base.installStatus;
5924 }
5925
5926 void enableComponentLP(String componentClassName) {
5927 disabledComponents.remove(componentClassName);
5928 enabledComponents.add(componentClassName);
5929 }
5930
5931 void disableComponentLP(String componentClassName) {
5932 enabledComponents.remove(componentClassName);
5933 disabledComponents.add(componentClassName);
5934 }
5935
5936 void restoreComponentLP(String componentClassName) {
5937 enabledComponents.remove(componentClassName);
5938 disabledComponents.remove(componentClassName);
5939 }
5940
5941 int currentEnabledStateLP(String componentName) {
5942 if (enabledComponents.contains(componentName)) {
5943 return COMPONENT_ENABLED_STATE_ENABLED;
5944 } else if (disabledComponents.contains(componentName)) {
5945 return COMPONENT_ENABLED_STATE_DISABLED;
5946 } else {
5947 return COMPONENT_ENABLED_STATE_DEFAULT;
5948 }
5949 }
5950 }
5951
5952 /**
5953 * Settings data for a particular package we know about.
5954 */
5955 static final class PackageSetting extends PackageSettingBase {
5956 int userId;
5957 PackageParser.Package pkg;
5958 SharedUserSetting sharedUser;
5959
5960 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005961 int pVersionCode, int pkgFlags) {
5962 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005963 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 @Override
5966 public String toString() {
5967 return "PackageSetting{"
5968 + Integer.toHexString(System.identityHashCode(this))
5969 + " " + name + "/" + userId + "}";
5970 }
5971 }
5972
5973 /**
5974 * Settings data for a particular shared user ID we know about.
5975 */
5976 static final class SharedUserSetting extends GrantedPermissions {
5977 final String name;
5978 int userId;
5979 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
5980 final PackageSignatures signatures = new PackageSignatures();
5981
5982 SharedUserSetting(String _name, int _pkgFlags) {
5983 super(_pkgFlags);
5984 name = _name;
5985 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005987 @Override
5988 public String toString() {
5989 return "SharedUserSetting{"
5990 + Integer.toHexString(System.identityHashCode(this))
5991 + " " + name + "/" + userId + "}";
5992 }
5993 }
5994
5995 /**
5996 * Holds information about dynamic settings.
5997 */
5998 private static final class Settings {
5999 private final File mSettingsFilename;
6000 private final File mBackupSettingsFilename;
6001 private final HashMap<String, PackageSetting> mPackages =
6002 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006003 // List of replaced system applications
6004 final HashMap<String, PackageSetting> mDisabledSysPackages =
6005 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006007 // The user's preferred activities associated with particular intent
6008 // filters.
6009 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6010 new IntentResolver<PreferredActivity, PreferredActivity>() {
6011 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006012 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006013 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006014 out.print(prefix); out.print(
6015 Integer.toHexString(System.identityHashCode(filter)));
6016 out.print(' ');
6017 out.print(filter.mActivity.flattenToShortString());
6018 out.print(" match=0x");
6019 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006021 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006022 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006023 out.print(prefix); out.print(" ");
6024 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 }
6026 }
6027 }
6028 };
6029 private final HashMap<String, SharedUserSetting> mSharedUsers =
6030 new HashMap<String, SharedUserSetting>();
6031 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6032 private final SparseArray<Object> mOtherUserIds =
6033 new SparseArray<Object>();
6034
6035 // For reading/writing settings file.
6036 private final ArrayList<Signature> mPastSignatures =
6037 new ArrayList<Signature>();
6038
6039 // Mapping from permission names to info about them.
6040 final HashMap<String, BasePermission> mPermissions =
6041 new HashMap<String, BasePermission>();
6042
6043 // Mapping from permission tree names to info about them.
6044 final HashMap<String, BasePermission> mPermissionTrees =
6045 new HashMap<String, BasePermission>();
6046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 private final StringBuilder mReadMessages = new StringBuilder();
6048
6049 private static final class PendingPackage extends PackageSettingBase {
6050 final int sharedId;
6051
6052 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006053 int sharedId, int pVersionCode, int pkgFlags) {
6054 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006055 this.sharedId = sharedId;
6056 }
6057 }
6058 private final ArrayList<PendingPackage> mPendingPackages
6059 = new ArrayList<PendingPackage>();
6060
6061 Settings() {
6062 File dataDir = Environment.getDataDirectory();
6063 File systemDir = new File(dataDir, "system");
6064 systemDir.mkdirs();
6065 FileUtils.setPermissions(systemDir.toString(),
6066 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6067 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6068 -1, -1);
6069 mSettingsFilename = new File(systemDir, "packages.xml");
6070 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6071 }
6072
6073 PackageSetting getPackageLP(PackageParser.Package pkg,
6074 SharedUserSetting sharedUser, File codePath, File resourcePath,
6075 int pkgFlags, boolean create, boolean add) {
6076 final String name = pkg.packageName;
6077 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006078 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 return p;
6080 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006081
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006082 PackageSetting peekPackageLP(String name) {
6083 return mPackages.get(name);
6084 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 PackageSetting p = mPackages.get(name);
6086 if (p != null && p.codePath.getPath().equals(codePath)) {
6087 return p;
6088 }
6089 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006090 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006091 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 void setInstallStatus(String pkgName, int status) {
6094 PackageSetting p = mPackages.get(pkgName);
6095 if(p != null) {
6096 if(p.getInstallStatus() != status) {
6097 p.setInstallStatus(status);
6098 }
6099 }
6100 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006101
Jacek Surazski65e13172009-04-28 15:26:38 +02006102 void setInstallerPackageName(String pkgName,
6103 String installerPkgName) {
6104 PackageSetting p = mPackages.get(pkgName);
6105 if(p != null) {
6106 p.setInstallerPackageName(installerPkgName);
6107 }
6108 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006109
Jacek Surazski65e13172009-04-28 15:26:38 +02006110 String getInstallerPackageName(String pkgName) {
6111 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006112 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006113 }
6114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 int getInstallStatus(String pkgName) {
6116 PackageSetting p = mPackages.get(pkgName);
6117 if(p != null) {
6118 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006119 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006120 return -1;
6121 }
6122
6123 SharedUserSetting getSharedUserLP(String name,
6124 int pkgFlags, boolean create) {
6125 SharedUserSetting s = mSharedUsers.get(name);
6126 if (s == null) {
6127 if (!create) {
6128 return null;
6129 }
6130 s = new SharedUserSetting(name, pkgFlags);
6131 if (MULTIPLE_APPLICATION_UIDS) {
6132 s.userId = newUserIdLP(s);
6133 } else {
6134 s.userId = FIRST_APPLICATION_UID;
6135 }
6136 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6137 // < 0 means we couldn't assign a userid; fall out and return
6138 // s, which is currently null
6139 if (s.userId >= 0) {
6140 mSharedUsers.put(name, s);
6141 }
6142 }
6143
6144 return s;
6145 }
6146
6147 int disableSystemPackageLP(String name) {
6148 PackageSetting p = mPackages.get(name);
6149 if(p == null) {
6150 Log.w(TAG, "Package:"+name+" is not an installed package");
6151 return -1;
6152 }
6153 PackageSetting dp = mDisabledSysPackages.get(name);
6154 // always make sure the system package code and resource paths dont change
6155 if(dp == null) {
6156 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6157 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6158 }
6159 mDisabledSysPackages.put(name, p);
6160 }
6161 return removePackageLP(name);
6162 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006164 PackageSetting enableSystemPackageLP(String name) {
6165 PackageSetting p = mDisabledSysPackages.get(name);
6166 if(p == null) {
6167 Log.w(TAG, "Package:"+name+" is not disabled");
6168 return null;
6169 }
6170 // Reset flag in ApplicationInfo object
6171 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6172 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6173 }
6174 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006175 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 mDisabledSysPackages.remove(name);
6177 return ret;
6178 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006181 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006182 PackageSetting p = mPackages.get(name);
6183 if (p != null) {
6184 if (p.userId == uid) {
6185 return p;
6186 }
6187 reportSettingsProblem(Log.ERROR,
6188 "Adding duplicate package, keeping first: " + name);
6189 return null;
6190 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006191 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 p.userId = uid;
6193 if (addUserIdLP(uid, p, name)) {
6194 mPackages.put(name, p);
6195 return p;
6196 }
6197 return null;
6198 }
6199
6200 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6201 SharedUserSetting s = mSharedUsers.get(name);
6202 if (s != null) {
6203 if (s.userId == uid) {
6204 return s;
6205 }
6206 reportSettingsProblem(Log.ERROR,
6207 "Adding duplicate shared user, keeping first: " + name);
6208 return null;
6209 }
6210 s = new SharedUserSetting(name, pkgFlags);
6211 s.userId = uid;
6212 if (addUserIdLP(uid, s, name)) {
6213 mSharedUsers.put(name, s);
6214 return s;
6215 }
6216 return null;
6217 }
6218
6219 private PackageSetting getPackageLP(String name,
6220 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006221 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006222 PackageSetting p = mPackages.get(name);
6223 if (p != null) {
6224 if (!p.codePath.equals(codePath)) {
6225 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006226 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006227 // This is an updated system app with versions in both system
6228 // and data partition. Just let the most recent version
6229 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006230 Log.w(TAG, "Trying to update system app code path from " +
6231 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006232 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006233 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006234 reportSettingsProblem(Log.WARN,
6235 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006236 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006238 }
6239 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006240 reportSettingsProblem(Log.WARN,
6241 "Package " + name + " shared user changed from "
6242 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6243 + " to "
6244 + (sharedUser != null ? sharedUser.name : "<nothing>")
6245 + "; replacing with new");
6246 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006247 } else {
6248 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6249 // If what we are scanning is a system package, then
6250 // make it so, regardless of whether it was previously
6251 // installed only in the data partition.
6252 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006254 }
6255 }
6256 if (p == null) {
6257 // Create a new PackageSettings entry. this can end up here because
6258 // of code path mismatch or user id mismatch of an updated system partition
6259 if (!create) {
6260 return null;
6261 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006262 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006264 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 if (sharedUser != null) {
6266 p.userId = sharedUser.userId;
6267 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006268 // Clone the setting here for disabled system packages
6269 PackageSetting dis = mDisabledSysPackages.get(name);
6270 if (dis != null) {
6271 // For disabled packages a new setting is created
6272 // from the existing user id. This still has to be
6273 // added to list of user id's
6274 // Copy signatures from previous setting
6275 if (dis.signatures.mSignatures != null) {
6276 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6277 }
6278 p.userId = dis.userId;
6279 // Clone permissions
6280 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6281 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6282 // Clone component info
6283 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6284 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6285 // Add new setting to list of user ids
6286 addUserIdLP(p.userId, p, name);
6287 } else {
6288 // Assign new user id
6289 p.userId = newUserIdLP(p);
6290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 } else {
6292 p.userId = FIRST_APPLICATION_UID;
6293 }
6294 if (p.userId < 0) {
6295 reportSettingsProblem(Log.WARN,
6296 "Package " + name + " could not be assigned a valid uid");
6297 return null;
6298 }
6299 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006300 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006302 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006303 }
6304 }
6305 return p;
6306 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006307
6308 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
6309 File codePath, File resourcePath) {
6310 p.pkg = pkg;
6311 // Update code path if needed
6312 if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
6313 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006314 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006315 p.codePath = codePath;
6316 p.codePathString = codePath.toString();
6317 }
6318 //Update resource path if needed
6319 if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
6320 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006321 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006322 p.resourcePath = resourcePath;
6323 p.resourcePathString = resourcePath.toString();
6324 }
6325 // Update version code if needed
6326 if (pkg.mVersionCode != p.versionCode) {
6327 p.versionCode = pkg.mVersionCode;
6328 }
6329 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6330 }
6331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006332 // Utility method that adds a PackageSetting to mPackages and
6333 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006334 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 SharedUserSetting sharedUser) {
6336 mPackages.put(name, p);
6337 if (sharedUser != null) {
6338 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6339 reportSettingsProblem(Log.ERROR,
6340 "Package " + p.name + " was user "
6341 + p.sharedUser + " but is now " + sharedUser
6342 + "; I am not changing its files so it will probably fail!");
6343 p.sharedUser.packages.remove(p);
6344 } else if (p.userId != sharedUser.userId) {
6345 reportSettingsProblem(Log.ERROR,
6346 "Package " + p.name + " was user id " + p.userId
6347 + " but is now user " + sharedUser
6348 + " with id " + sharedUser.userId
6349 + "; I am not changing its files so it will probably fail!");
6350 }
6351
6352 sharedUser.packages.add(p);
6353 p.sharedUser = sharedUser;
6354 p.userId = sharedUser.userId;
6355 }
6356 }
6357
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006358 /*
6359 * Update the shared user setting when a package using
6360 * specifying the shared user id is removed. The gids
6361 * associated with each permission of the deleted package
6362 * are removed from the shared user's gid list only if its
6363 * not in use by other permissions of packages in the
6364 * shared user setting.
6365 */
6366 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6368 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6369 return;
6370 }
6371 // No sharedUserId
6372 if (deletedPs.sharedUser == null) {
6373 return;
6374 }
6375 SharedUserSetting sus = deletedPs.sharedUser;
6376 // Update permissions
6377 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6378 boolean used = false;
6379 if (!sus.grantedPermissions.contains (eachPerm)) {
6380 continue;
6381 }
6382 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006383 if (pkg.pkg != null &&
6384 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6385 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006386 used = true;
6387 break;
6388 }
6389 }
6390 if (!used) {
6391 // can safely delete this permission from list
6392 sus.grantedPermissions.remove(eachPerm);
6393 sus.loadedPermissions.remove(eachPerm);
6394 }
6395 }
6396 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006397 int newGids[] = globalGids;
6398 for (String eachPerm : sus.grantedPermissions) {
6399 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006400 if (bp != null) {
6401 newGids = appendInts(newGids, bp.gids);
6402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006403 }
6404 sus.gids = newGids;
6405 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 private int removePackageLP(String name) {
6408 PackageSetting p = mPackages.get(name);
6409 if (p != null) {
6410 mPackages.remove(name);
6411 if (p.sharedUser != null) {
6412 p.sharedUser.packages.remove(p);
6413 if (p.sharedUser.packages.size() == 0) {
6414 mSharedUsers.remove(p.sharedUser.name);
6415 removeUserIdLP(p.sharedUser.userId);
6416 return p.sharedUser.userId;
6417 }
6418 } else {
6419 removeUserIdLP(p.userId);
6420 return p.userId;
6421 }
6422 }
6423 return -1;
6424 }
6425
6426 private boolean addUserIdLP(int uid, Object obj, Object name) {
6427 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6428 return false;
6429 }
6430
6431 if (uid >= FIRST_APPLICATION_UID) {
6432 int N = mUserIds.size();
6433 final int index = uid - FIRST_APPLICATION_UID;
6434 while (index >= N) {
6435 mUserIds.add(null);
6436 N++;
6437 }
6438 if (mUserIds.get(index) != null) {
6439 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006440 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 + " name=" + name);
6442 return false;
6443 }
6444 mUserIds.set(index, obj);
6445 } else {
6446 if (mOtherUserIds.get(uid) != null) {
6447 reportSettingsProblem(Log.ERROR,
6448 "Adding duplicate shared id: " + uid
6449 + " name=" + name);
6450 return false;
6451 }
6452 mOtherUserIds.put(uid, obj);
6453 }
6454 return true;
6455 }
6456
6457 public Object getUserIdLP(int uid) {
6458 if (uid >= FIRST_APPLICATION_UID) {
6459 int N = mUserIds.size();
6460 final int index = uid - FIRST_APPLICATION_UID;
6461 return index < N ? mUserIds.get(index) : null;
6462 } else {
6463 return mOtherUserIds.get(uid);
6464 }
6465 }
6466
6467 private void removeUserIdLP(int uid) {
6468 if (uid >= FIRST_APPLICATION_UID) {
6469 int N = mUserIds.size();
6470 final int index = uid - FIRST_APPLICATION_UID;
6471 if (index < N) mUserIds.set(index, null);
6472 } else {
6473 mOtherUserIds.remove(uid);
6474 }
6475 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 void writeLP() {
6478 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6479
6480 // Keep the old settings around until we know the new ones have
6481 // been successfully written.
6482 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006483 // Presence of backup settings file indicates that we failed
6484 // to persist settings earlier. So preserve the older
6485 // backup for future reference since the current settings
6486 // might have been corrupted.
6487 if (!mBackupSettingsFilename.exists()) {
6488 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6489 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6490 return;
6491 }
6492 } else {
6493 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006495 }
6496
6497 mPastSignatures.clear();
6498
6499 try {
6500 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6501
6502 //XmlSerializer serializer = XmlUtils.serializerInstance();
6503 XmlSerializer serializer = new FastXmlSerializer();
6504 serializer.setOutput(str, "utf-8");
6505 serializer.startDocument(null, true);
6506 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6507
6508 serializer.startTag(null, "packages");
6509
6510 serializer.startTag(null, "permission-trees");
6511 for (BasePermission bp : mPermissionTrees.values()) {
6512 writePermission(serializer, bp);
6513 }
6514 serializer.endTag(null, "permission-trees");
6515
6516 serializer.startTag(null, "permissions");
6517 for (BasePermission bp : mPermissions.values()) {
6518 writePermission(serializer, bp);
6519 }
6520 serializer.endTag(null, "permissions");
6521
6522 for (PackageSetting pkg : mPackages.values()) {
6523 writePackage(serializer, pkg);
6524 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 for (PackageSetting pkg : mDisabledSysPackages.values()) {
6527 writeDisabledSysPackage(serializer, pkg);
6528 }
6529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 serializer.startTag(null, "preferred-activities");
6531 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
6532 serializer.startTag(null, "item");
6533 pa.writeToXml(serializer);
6534 serializer.endTag(null, "item");
6535 }
6536 serializer.endTag(null, "preferred-activities");
6537
6538 for (SharedUserSetting usr : mSharedUsers.values()) {
6539 serializer.startTag(null, "shared-user");
6540 serializer.attribute(null, "name", usr.name);
6541 serializer.attribute(null, "userId",
6542 Integer.toString(usr.userId));
6543 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
6544 serializer.startTag(null, "perms");
6545 for (String name : usr.grantedPermissions) {
6546 serializer.startTag(null, "item");
6547 serializer.attribute(null, "name", name);
6548 serializer.endTag(null, "item");
6549 }
6550 serializer.endTag(null, "perms");
6551 serializer.endTag(null, "shared-user");
6552 }
6553
6554 serializer.endTag(null, "packages");
6555
6556 serializer.endDocument();
6557
6558 str.flush();
6559 str.close();
6560
6561 // New settings successfully written, old ones are no longer
6562 // needed.
6563 mBackupSettingsFilename.delete();
6564 FileUtils.setPermissions(mSettingsFilename.toString(),
6565 FileUtils.S_IRUSR|FileUtils.S_IWUSR
6566 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
6567 |FileUtils.S_IROTH,
6568 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006569 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006570
6571 } catch(XmlPullParserException e) {
6572 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 -08006573 } catch(java.io.IOException e) {
6574 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 -08006575 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07006576 // Clean up partially written file
6577 if (mSettingsFilename.exists()) {
6578 if (!mSettingsFilename.delete()) {
6579 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
6580 }
6581 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 //Debug.stopMethodTracing();
6583 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006584
6585 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006586 throws java.io.IOException {
6587 serializer.startTag(null, "updated-package");
6588 serializer.attribute(null, "name", pkg.name);
6589 serializer.attribute(null, "codePath", pkg.codePathString);
6590 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006591 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6593 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6594 }
6595 if (pkg.sharedUser == null) {
6596 serializer.attribute(null, "userId",
6597 Integer.toString(pkg.userId));
6598 } else {
6599 serializer.attribute(null, "sharedUserId",
6600 Integer.toString(pkg.userId));
6601 }
6602 serializer.startTag(null, "perms");
6603 if (pkg.sharedUser == null) {
6604 // If this is a shared user, the permissions will
6605 // be written there. We still need to write an
6606 // empty permissions list so permissionsFixed will
6607 // be set.
6608 for (final String name : pkg.grantedPermissions) {
6609 BasePermission bp = mPermissions.get(name);
6610 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
6611 // We only need to write signature or system permissions but this wont
6612 // match the semantics of grantedPermissions. So write all permissions.
6613 serializer.startTag(null, "item");
6614 serializer.attribute(null, "name", name);
6615 serializer.endTag(null, "item");
6616 }
6617 }
6618 }
6619 serializer.endTag(null, "perms");
6620 serializer.endTag(null, "updated-package");
6621 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006622
6623 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 throws java.io.IOException {
6625 serializer.startTag(null, "package");
6626 serializer.attribute(null, "name", pkg.name);
6627 serializer.attribute(null, "codePath", pkg.codePathString);
6628 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
6629 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
6630 }
6631 serializer.attribute(null, "system",
6632 (pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
6633 ? "true" : "false");
6634 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006635 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 if (pkg.sharedUser == null) {
6637 serializer.attribute(null, "userId",
6638 Integer.toString(pkg.userId));
6639 } else {
6640 serializer.attribute(null, "sharedUserId",
6641 Integer.toString(pkg.userId));
6642 }
6643 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
6644 serializer.attribute(null, "enabled",
6645 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
6646 ? "true" : "false");
6647 }
6648 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
6649 serializer.attribute(null, "installStatus", "false");
6650 }
Jacek Surazski65e13172009-04-28 15:26:38 +02006651 if (pkg.installerPackageName != null) {
6652 serializer.attribute(null, "installer", pkg.installerPackageName);
6653 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
6655 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
6656 serializer.startTag(null, "perms");
6657 if (pkg.sharedUser == null) {
6658 // If this is a shared user, the permissions will
6659 // be written there. We still need to write an
6660 // empty permissions list so permissionsFixed will
6661 // be set.
6662 for (final String name : pkg.grantedPermissions) {
6663 serializer.startTag(null, "item");
6664 serializer.attribute(null, "name", name);
6665 serializer.endTag(null, "item");
6666 }
6667 }
6668 serializer.endTag(null, "perms");
6669 }
6670 if (pkg.disabledComponents.size() > 0) {
6671 serializer.startTag(null, "disabled-components");
6672 for (final String name : pkg.disabledComponents) {
6673 serializer.startTag(null, "item");
6674 serializer.attribute(null, "name", name);
6675 serializer.endTag(null, "item");
6676 }
6677 serializer.endTag(null, "disabled-components");
6678 }
6679 if (pkg.enabledComponents.size() > 0) {
6680 serializer.startTag(null, "enabled-components");
6681 for (final String name : pkg.enabledComponents) {
6682 serializer.startTag(null, "item");
6683 serializer.attribute(null, "name", name);
6684 serializer.endTag(null, "item");
6685 }
6686 serializer.endTag(null, "enabled-components");
6687 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006689 serializer.endTag(null, "package");
6690 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 void writePermission(XmlSerializer serializer, BasePermission bp)
6693 throws XmlPullParserException, java.io.IOException {
6694 if (bp.type != BasePermission.TYPE_BUILTIN
6695 && bp.sourcePackage != null) {
6696 serializer.startTag(null, "item");
6697 serializer.attribute(null, "name", bp.name);
6698 serializer.attribute(null, "package", bp.sourcePackage);
6699 if (DEBUG_SETTINGS) Log.v(TAG,
6700 "Writing perm: name=" + bp.name + " type=" + bp.type);
6701 if (bp.type == BasePermission.TYPE_DYNAMIC) {
6702 PermissionInfo pi = bp.perm != null ? bp.perm.info
6703 : bp.pendingInfo;
6704 if (pi != null) {
6705 serializer.attribute(null, "type", "dynamic");
6706 if (pi.icon != 0) {
6707 serializer.attribute(null, "icon",
6708 Integer.toString(pi.icon));
6709 }
6710 if (pi.nonLocalizedLabel != null) {
6711 serializer.attribute(null, "label",
6712 pi.nonLocalizedLabel.toString());
6713 }
6714 if (pi.protectionLevel !=
6715 PermissionInfo.PROTECTION_NORMAL) {
6716 serializer.attribute(null, "protection",
6717 Integer.toString(pi.protectionLevel));
6718 }
6719 }
6720 }
6721 serializer.endTag(null, "item");
6722 }
6723 }
6724
6725 String getReadMessagesLP() {
6726 return mReadMessages.toString();
6727 }
6728
6729 ArrayList<String> getListOfIncompleteInstallPackages() {
6730 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
6731 Iterator<String> its = kList.iterator();
6732 ArrayList<String> ret = new ArrayList<String>();
6733 while(its.hasNext()) {
6734 String key = its.next();
6735 PackageSetting ps = mPackages.get(key);
6736 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
6737 ret.add(key);
6738 }
6739 }
6740 return ret;
6741 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006743 boolean readLP() {
6744 FileInputStream str = null;
6745 if (mBackupSettingsFilename.exists()) {
6746 try {
6747 str = new FileInputStream(mBackupSettingsFilename);
6748 mReadMessages.append("Reading from backup settings file\n");
6749 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006750 if (mSettingsFilename.exists()) {
6751 // If both the backup and settings file exist, we
6752 // ignore the settings since it might have been
6753 // corrupted.
6754 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
6755 mSettingsFilename.delete();
6756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006757 } catch (java.io.IOException e) {
6758 // We'll try for the normal settings file.
6759 }
6760 }
6761
6762 mPastSignatures.clear();
6763
6764 try {
6765 if (str == null) {
6766 if (!mSettingsFilename.exists()) {
6767 mReadMessages.append("No settings file found\n");
6768 Log.i(TAG, "No current settings file!");
6769 return false;
6770 }
6771 str = new FileInputStream(mSettingsFilename);
6772 }
6773 XmlPullParser parser = Xml.newPullParser();
6774 parser.setInput(str, null);
6775
6776 int type;
6777 while ((type=parser.next()) != XmlPullParser.START_TAG
6778 && type != XmlPullParser.END_DOCUMENT) {
6779 ;
6780 }
6781
6782 if (type != XmlPullParser.START_TAG) {
6783 mReadMessages.append("No start tag found in settings file\n");
6784 Log.e(TAG, "No start tag found in package manager settings");
6785 return false;
6786 }
6787
6788 int outerDepth = parser.getDepth();
6789 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6790 && (type != XmlPullParser.END_TAG
6791 || parser.getDepth() > outerDepth)) {
6792 if (type == XmlPullParser.END_TAG
6793 || type == XmlPullParser.TEXT) {
6794 continue;
6795 }
6796
6797 String tagName = parser.getName();
6798 if (tagName.equals("package")) {
6799 readPackageLP(parser);
6800 } else if (tagName.equals("permissions")) {
6801 readPermissionsLP(mPermissions, parser);
6802 } else if (tagName.equals("permission-trees")) {
6803 readPermissionsLP(mPermissionTrees, parser);
6804 } else if (tagName.equals("shared-user")) {
6805 readSharedUserLP(parser);
6806 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08006807 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 } else if (tagName.equals("preferred-activities")) {
6809 readPreferredActivitiesLP(parser);
6810 } else if(tagName.equals("updated-package")) {
6811 readDisabledSysPackageLP(parser);
6812 } else {
6813 Log.w(TAG, "Unknown element under <packages>: "
6814 + parser.getName());
6815 XmlUtils.skipCurrentTag(parser);
6816 }
6817 }
6818
6819 str.close();
6820
6821 } catch(XmlPullParserException e) {
6822 mReadMessages.append("Error reading: " + e.toString());
6823 Log.e(TAG, "Error reading package manager settings", e);
6824
6825 } catch(java.io.IOException e) {
6826 mReadMessages.append("Error reading: " + e.toString());
6827 Log.e(TAG, "Error reading package manager settings", e);
6828
6829 }
6830
6831 int N = mPendingPackages.size();
6832 for (int i=0; i<N; i++) {
6833 final PendingPackage pp = mPendingPackages.get(i);
6834 Object idObj = getUserIdLP(pp.sharedId);
6835 if (idObj != null && idObj instanceof SharedUserSetting) {
6836 PackageSetting p = getPackageLP(pp.name,
6837 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006838 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006839 if (p == null) {
6840 Log.w(TAG, "Unable to create application package for "
6841 + pp.name);
6842 continue;
6843 }
6844 p.copyFrom(pp);
6845 } else if (idObj != null) {
6846 String msg = "Bad package setting: package " + pp.name
6847 + " has shared uid " + pp.sharedId
6848 + " that is not a shared uid\n";
6849 mReadMessages.append(msg);
6850 Log.e(TAG, msg);
6851 } else {
6852 String msg = "Bad package setting: package " + pp.name
6853 + " has shared uid " + pp.sharedId
6854 + " that is not defined\n";
6855 mReadMessages.append(msg);
6856 Log.e(TAG, msg);
6857 }
6858 }
6859 mPendingPackages.clear();
6860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006861 mReadMessages.append("Read completed successfully: "
6862 + mPackages.size() + " packages, "
6863 + mSharedUsers.size() + " shared uids\n");
6864
6865 return true;
6866 }
6867
6868 private int readInt(XmlPullParser parser, String ns, String name,
6869 int defValue) {
6870 String v = parser.getAttributeValue(ns, name);
6871 try {
6872 if (v == null) {
6873 return defValue;
6874 }
6875 return Integer.parseInt(v);
6876 } catch (NumberFormatException e) {
6877 reportSettingsProblem(Log.WARN,
6878 "Error in package manager settings: attribute " +
6879 name + " has bad integer value " + v + " at "
6880 + parser.getPositionDescription());
6881 }
6882 return defValue;
6883 }
6884
6885 private void readPermissionsLP(HashMap<String, BasePermission> out,
6886 XmlPullParser parser)
6887 throws IOException, XmlPullParserException {
6888 int outerDepth = parser.getDepth();
6889 int type;
6890 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6891 && (type != XmlPullParser.END_TAG
6892 || parser.getDepth() > outerDepth)) {
6893 if (type == XmlPullParser.END_TAG
6894 || type == XmlPullParser.TEXT) {
6895 continue;
6896 }
6897
6898 String tagName = parser.getName();
6899 if (tagName.equals("item")) {
6900 String name = parser.getAttributeValue(null, "name");
6901 String sourcePackage = parser.getAttributeValue(null, "package");
6902 String ptype = parser.getAttributeValue(null, "type");
6903 if (name != null && sourcePackage != null) {
6904 boolean dynamic = "dynamic".equals(ptype);
6905 BasePermission bp = new BasePermission(name, sourcePackage,
6906 dynamic
6907 ? BasePermission.TYPE_DYNAMIC
6908 : BasePermission.TYPE_NORMAL);
6909 if (dynamic) {
6910 PermissionInfo pi = new PermissionInfo();
6911 pi.packageName = sourcePackage.intern();
6912 pi.name = name.intern();
6913 pi.icon = readInt(parser, null, "icon", 0);
6914 pi.nonLocalizedLabel = parser.getAttributeValue(
6915 null, "label");
6916 pi.protectionLevel = readInt(parser, null, "protection",
6917 PermissionInfo.PROTECTION_NORMAL);
6918 bp.pendingInfo = pi;
6919 }
6920 out.put(bp.name, bp);
6921 } else {
6922 reportSettingsProblem(Log.WARN,
6923 "Error in package manager settings: permissions has"
6924 + " no name at " + parser.getPositionDescription());
6925 }
6926 } else {
6927 reportSettingsProblem(Log.WARN,
6928 "Unknown element reading permissions: "
6929 + parser.getName() + " at "
6930 + parser.getPositionDescription());
6931 }
6932 XmlUtils.skipCurrentTag(parser);
6933 }
6934 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 private void readDisabledSysPackageLP(XmlPullParser parser)
6937 throws XmlPullParserException, IOException {
6938 String name = parser.getAttributeValue(null, "name");
6939 String codePathStr = parser.getAttributeValue(null, "codePath");
6940 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
6941 if(resourcePathStr == null) {
6942 resourcePathStr = codePathStr;
6943 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006944 String version = parser.getAttributeValue(null, "version");
6945 int versionCode = 0;
6946 if (version != null) {
6947 try {
6948 versionCode = Integer.parseInt(version);
6949 } catch (NumberFormatException e) {
6950 }
6951 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006953 int pkgFlags = 0;
6954 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006955 PackageSetting ps = new PackageSetting(name,
6956 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006957 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 String timeStampStr = parser.getAttributeValue(null, "ts");
6959 if (timeStampStr != null) {
6960 try {
6961 long timeStamp = Long.parseLong(timeStampStr);
6962 ps.setTimeStamp(timeStamp, timeStampStr);
6963 } catch (NumberFormatException e) {
6964 }
6965 }
6966 String idStr = parser.getAttributeValue(null, "userId");
6967 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
6968 if(ps.userId <= 0) {
6969 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
6970 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
6971 }
6972 int outerDepth = parser.getDepth();
6973 int type;
6974 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6975 && (type != XmlPullParser.END_TAG
6976 || parser.getDepth() > outerDepth)) {
6977 if (type == XmlPullParser.END_TAG
6978 || type == XmlPullParser.TEXT) {
6979 continue;
6980 }
6981
6982 String tagName = parser.getName();
6983 if (tagName.equals("perms")) {
6984 readGrantedPermissionsLP(parser,
6985 ps.grantedPermissions);
6986 } else {
6987 reportSettingsProblem(Log.WARN,
6988 "Unknown element under <updated-package>: "
6989 + parser.getName());
6990 XmlUtils.skipCurrentTag(parser);
6991 }
6992 }
6993 mDisabledSysPackages.put(name, ps);
6994 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 private void readPackageLP(XmlPullParser parser)
6997 throws XmlPullParserException, IOException {
6998 String name = null;
6999 String idStr = null;
7000 String sharedIdStr = null;
7001 String codePathStr = null;
7002 String resourcePathStr = null;
7003 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007004 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007005 int pkgFlags = 0;
7006 String timeStampStr;
7007 long timeStamp = 0;
7008 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007009 String version = null;
7010 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007011 try {
7012 name = parser.getAttributeValue(null, "name");
7013 idStr = parser.getAttributeValue(null, "userId");
7014 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7015 codePathStr = parser.getAttributeValue(null, "codePath");
7016 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007017 version = parser.getAttributeValue(null, "version");
7018 if (version != null) {
7019 try {
7020 versionCode = Integer.parseInt(version);
7021 } catch (NumberFormatException e) {
7022 }
7023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007024 systemStr = parser.getAttributeValue(null, "system");
Jacek Surazski65e13172009-04-28 15:26:38 +02007025 installerPackageName = parser.getAttributeValue(null, "installer");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 if (systemStr != null) {
7027 if ("true".equals(systemStr)) {
7028 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7029 }
7030 } else {
7031 // Old settings that don't specify system... just treat
7032 // them as system, good enough.
7033 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7034 }
7035 timeStampStr = parser.getAttributeValue(null, "ts");
7036 if (timeStampStr != null) {
7037 try {
7038 timeStamp = Long.parseLong(timeStampStr);
7039 } catch (NumberFormatException e) {
7040 }
7041 }
7042 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7043 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7044 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7045 if (resourcePathStr == null) {
7046 resourcePathStr = codePathStr;
7047 }
7048 if (name == null) {
7049 reportSettingsProblem(Log.WARN,
7050 "Error in package manager settings: <package> has no name at "
7051 + parser.getPositionDescription());
7052 } else if (codePathStr == null) {
7053 reportSettingsProblem(Log.WARN,
7054 "Error in package manager settings: <package> has no codePath at "
7055 + parser.getPositionDescription());
7056 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007057 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007058 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7060 + ": userId=" + userId + " pkg=" + packageSetting);
7061 if (packageSetting == null) {
7062 reportSettingsProblem(Log.ERROR,
7063 "Failure adding uid " + userId
7064 + " while parsing settings at "
7065 + parser.getPositionDescription());
7066 } else {
7067 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7068 }
7069 } else if (sharedIdStr != null) {
7070 userId = sharedIdStr != null
7071 ? Integer.parseInt(sharedIdStr) : 0;
7072 if (userId > 0) {
7073 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007074 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007075 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7076 mPendingPackages.add((PendingPackage) packageSetting);
7077 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7078 + ": sharedUserId=" + userId + " pkg="
7079 + packageSetting);
7080 } else {
7081 reportSettingsProblem(Log.WARN,
7082 "Error in package manager settings: package "
7083 + name + " has bad sharedId " + sharedIdStr
7084 + " at " + parser.getPositionDescription());
7085 }
7086 } else {
7087 reportSettingsProblem(Log.WARN,
7088 "Error in package manager settings: package "
7089 + name + " has bad userId " + idStr + " at "
7090 + parser.getPositionDescription());
7091 }
7092 } catch (NumberFormatException e) {
7093 reportSettingsProblem(Log.WARN,
7094 "Error in package manager settings: package "
7095 + name + " has bad userId " + idStr + " at "
7096 + parser.getPositionDescription());
7097 }
7098 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007099 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 final String enabledStr = parser.getAttributeValue(null, "enabled");
7101 if (enabledStr != null) {
7102 if (enabledStr.equalsIgnoreCase("true")) {
7103 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7104 } else if (enabledStr.equalsIgnoreCase("false")) {
7105 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7106 } else if (enabledStr.equalsIgnoreCase("default")) {
7107 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7108 } else {
7109 reportSettingsProblem(Log.WARN,
7110 "Error in package manager settings: package "
7111 + name + " has bad enabled value: " + idStr
7112 + " at " + parser.getPositionDescription());
7113 }
7114 } else {
7115 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7116 }
7117 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7118 if (installStatusStr != null) {
7119 if (installStatusStr.equalsIgnoreCase("false")) {
7120 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7121 } else {
7122 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7123 }
7124 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007126 int outerDepth = parser.getDepth();
7127 int type;
7128 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7129 && (type != XmlPullParser.END_TAG
7130 || parser.getDepth() > outerDepth)) {
7131 if (type == XmlPullParser.END_TAG
7132 || type == XmlPullParser.TEXT) {
7133 continue;
7134 }
7135
7136 String tagName = parser.getName();
7137 if (tagName.equals("disabled-components")) {
7138 readDisabledComponentsLP(packageSetting, parser);
7139 } else if (tagName.equals("enabled-components")) {
7140 readEnabledComponentsLP(packageSetting, parser);
7141 } else if (tagName.equals("sigs")) {
7142 packageSetting.signatures.readXml(parser, mPastSignatures);
7143 } else if (tagName.equals("perms")) {
7144 readGrantedPermissionsLP(parser,
7145 packageSetting.loadedPermissions);
7146 packageSetting.permissionsFixed = true;
7147 } else {
7148 reportSettingsProblem(Log.WARN,
7149 "Unknown element under <package>: "
7150 + parser.getName());
7151 XmlUtils.skipCurrentTag(parser);
7152 }
7153 }
7154 } else {
7155 XmlUtils.skipCurrentTag(parser);
7156 }
7157 }
7158
7159 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7160 XmlPullParser parser)
7161 throws IOException, XmlPullParserException {
7162 int outerDepth = parser.getDepth();
7163 int type;
7164 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7165 && (type != XmlPullParser.END_TAG
7166 || parser.getDepth() > outerDepth)) {
7167 if (type == XmlPullParser.END_TAG
7168 || type == XmlPullParser.TEXT) {
7169 continue;
7170 }
7171
7172 String tagName = parser.getName();
7173 if (tagName.equals("item")) {
7174 String name = parser.getAttributeValue(null, "name");
7175 if (name != null) {
7176 packageSetting.disabledComponents.add(name.intern());
7177 } else {
7178 reportSettingsProblem(Log.WARN,
7179 "Error in package manager settings: <disabled-components> has"
7180 + " no name at " + parser.getPositionDescription());
7181 }
7182 } else {
7183 reportSettingsProblem(Log.WARN,
7184 "Unknown element under <disabled-components>: "
7185 + parser.getName());
7186 }
7187 XmlUtils.skipCurrentTag(parser);
7188 }
7189 }
7190
7191 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7192 XmlPullParser parser)
7193 throws IOException, XmlPullParserException {
7194 int outerDepth = parser.getDepth();
7195 int type;
7196 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7197 && (type != XmlPullParser.END_TAG
7198 || parser.getDepth() > outerDepth)) {
7199 if (type == XmlPullParser.END_TAG
7200 || type == XmlPullParser.TEXT) {
7201 continue;
7202 }
7203
7204 String tagName = parser.getName();
7205 if (tagName.equals("item")) {
7206 String name = parser.getAttributeValue(null, "name");
7207 if (name != null) {
7208 packageSetting.enabledComponents.add(name.intern());
7209 } else {
7210 reportSettingsProblem(Log.WARN,
7211 "Error in package manager settings: <enabled-components> has"
7212 + " no name at " + parser.getPositionDescription());
7213 }
7214 } else {
7215 reportSettingsProblem(Log.WARN,
7216 "Unknown element under <enabled-components>: "
7217 + parser.getName());
7218 }
7219 XmlUtils.skipCurrentTag(parser);
7220 }
7221 }
7222
7223 private void readSharedUserLP(XmlPullParser parser)
7224 throws XmlPullParserException, IOException {
7225 String name = null;
7226 String idStr = null;
7227 int pkgFlags = 0;
7228 SharedUserSetting su = null;
7229 try {
7230 name = parser.getAttributeValue(null, "name");
7231 idStr = parser.getAttributeValue(null, "userId");
7232 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7233 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7234 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7235 }
7236 if (name == null) {
7237 reportSettingsProblem(Log.WARN,
7238 "Error in package manager settings: <shared-user> has no name at "
7239 + parser.getPositionDescription());
7240 } else if (userId == 0) {
7241 reportSettingsProblem(Log.WARN,
7242 "Error in package manager settings: shared-user "
7243 + name + " has bad userId " + idStr + " at "
7244 + parser.getPositionDescription());
7245 } else {
7246 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7247 reportSettingsProblem(Log.ERROR,
7248 "Occurred while parsing settings at "
7249 + parser.getPositionDescription());
7250 }
7251 }
7252 } catch (NumberFormatException e) {
7253 reportSettingsProblem(Log.WARN,
7254 "Error in package manager settings: package "
7255 + name + " has bad userId " + idStr + " at "
7256 + parser.getPositionDescription());
7257 };
7258
7259 if (su != null) {
7260 int outerDepth = parser.getDepth();
7261 int type;
7262 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7263 && (type != XmlPullParser.END_TAG
7264 || parser.getDepth() > outerDepth)) {
7265 if (type == XmlPullParser.END_TAG
7266 || type == XmlPullParser.TEXT) {
7267 continue;
7268 }
7269
7270 String tagName = parser.getName();
7271 if (tagName.equals("sigs")) {
7272 su.signatures.readXml(parser, mPastSignatures);
7273 } else if (tagName.equals("perms")) {
7274 readGrantedPermissionsLP(parser, su.loadedPermissions);
7275 } else {
7276 reportSettingsProblem(Log.WARN,
7277 "Unknown element under <shared-user>: "
7278 + parser.getName());
7279 XmlUtils.skipCurrentTag(parser);
7280 }
7281 }
7282
7283 } else {
7284 XmlUtils.skipCurrentTag(parser);
7285 }
7286 }
7287
7288 private void readGrantedPermissionsLP(XmlPullParser parser,
7289 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7290 int outerDepth = parser.getDepth();
7291 int type;
7292 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7293 && (type != XmlPullParser.END_TAG
7294 || parser.getDepth() > outerDepth)) {
7295 if (type == XmlPullParser.END_TAG
7296 || type == XmlPullParser.TEXT) {
7297 continue;
7298 }
7299
7300 String tagName = parser.getName();
7301 if (tagName.equals("item")) {
7302 String name = parser.getAttributeValue(null, "name");
7303 if (name != null) {
7304 outPerms.add(name.intern());
7305 } else {
7306 reportSettingsProblem(Log.WARN,
7307 "Error in package manager settings: <perms> has"
7308 + " no name at " + parser.getPositionDescription());
7309 }
7310 } else {
7311 reportSettingsProblem(Log.WARN,
7312 "Unknown element under <perms>: "
7313 + parser.getName());
7314 }
7315 XmlUtils.skipCurrentTag(parser);
7316 }
7317 }
7318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007319 private void readPreferredActivitiesLP(XmlPullParser parser)
7320 throws XmlPullParserException, IOException {
7321 int outerDepth = parser.getDepth();
7322 int type;
7323 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7324 && (type != XmlPullParser.END_TAG
7325 || parser.getDepth() > outerDepth)) {
7326 if (type == XmlPullParser.END_TAG
7327 || type == XmlPullParser.TEXT) {
7328 continue;
7329 }
7330
7331 String tagName = parser.getName();
7332 if (tagName.equals("item")) {
7333 PreferredActivity pa = new PreferredActivity(parser);
7334 if (pa.mParseError == null) {
7335 mPreferredActivities.addFilter(pa);
7336 } else {
7337 reportSettingsProblem(Log.WARN,
7338 "Error in package manager settings: <preferred-activity> "
7339 + pa.mParseError + " at "
7340 + parser.getPositionDescription());
7341 }
7342 } else {
7343 reportSettingsProblem(Log.WARN,
7344 "Unknown element under <preferred-activities>: "
7345 + parser.getName());
7346 XmlUtils.skipCurrentTag(parser);
7347 }
7348 }
7349 }
7350
7351 // Returns -1 if we could not find an available UserId to assign
7352 private int newUserIdLP(Object obj) {
7353 // Let's be stupidly inefficient for now...
7354 final int N = mUserIds.size();
7355 for (int i=0; i<N; i++) {
7356 if (mUserIds.get(i) == null) {
7357 mUserIds.set(i, obj);
7358 return FIRST_APPLICATION_UID + i;
7359 }
7360 }
7361
7362 // None left?
7363 if (N >= MAX_APPLICATION_UIDS) {
7364 return -1;
7365 }
7366
7367 mUserIds.add(obj);
7368 return FIRST_APPLICATION_UID + N;
7369 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007371 public PackageSetting getDisabledSystemPkg(String name) {
7372 synchronized(mPackages) {
7373 PackageSetting ps = mDisabledSysPackages.get(name);
7374 return ps;
7375 }
7376 }
7377
7378 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7379 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7380 if (Config.LOGV) {
7381 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7382 + " componentName = " + componentInfo.name);
7383 Log.v(TAG, "enabledComponents: "
7384 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7385 Log.v(TAG, "disabledComponents: "
7386 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7387 }
7388 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7389 || ((componentInfo.enabled
7390 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7391 || (componentInfo.applicationInfo.enabled
7392 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7393 && !packageSettings.disabledComponents.contains(componentInfo.name))
7394 || packageSettings.enabledComponents.contains(componentInfo.name));
7395 }
7396 }
7397}