blob: 4801817bf594ab254b8b6bb3f3cb8aa899ee7e6e [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
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080019import com.android.internal.app.IMediaContainerService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.app.ResolverActivity;
Tom Taylord4a47292009-12-21 13:59:18 -080021import com.android.common.FastXmlSerializer;
22import com.android.common.XmlUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26import org.xmlpull.v1.XmlSerializer;
27
28import android.app.ActivityManagerNative;
29import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070034import android.content.IntentSender;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080035import android.content.ServiceConnection;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070036import android.content.IntentSender.SendIntentException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.pm.ActivityInfo;
38import android.content.pm.ApplicationInfo;
39import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070040import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.content.pm.IPackageDataObserver;
42import android.content.pm.IPackageDeleteObserver;
43import android.content.pm.IPackageInstallObserver;
44import android.content.pm.IPackageManager;
45import android.content.pm.IPackageStatsObserver;
46import android.content.pm.InstrumentationInfo;
47import android.content.pm.PackageInfo;
48import android.content.pm.PackageManager;
49import android.content.pm.PackageStats;
50import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
51import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
52import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
53import static android.content.pm.PackageManager.PKG_INSTALL_COMPLETE;
54import static android.content.pm.PackageManager.PKG_INSTALL_INCOMPLETE;
55import android.content.pm.PackageParser;
56import android.content.pm.PermissionInfo;
57import android.content.pm.PermissionGroupInfo;
58import android.content.pm.ProviderInfo;
59import android.content.pm.ResolveInfo;
60import android.content.pm.ServiceInfo;
61import android.content.pm.Signature;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.net.Uri;
63import android.os.Binder;
Dianne Hackborn851a5412009-05-08 12:06:44 -070064import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.Bundle;
66import android.os.HandlerThread;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -080067import android.os.IBinder;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -070068import android.os.Looper;
69import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.os.Parcel;
71import android.os.RemoteException;
72import android.os.Environment;
73import android.os.FileObserver;
74import android.os.FileUtils;
75import android.os.Handler;
San Mehatbe16cb12010-01-29 05:35:35 -080076import android.os.MountServiceResultCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.ParcelFileDescriptor;
78import android.os.Process;
79import android.os.ServiceManager;
80import android.os.SystemClock;
81import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080082import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.util.*;
84import android.view.Display;
85import android.view.WindowManager;
86
87import java.io.File;
88import java.io.FileDescriptor;
89import java.io.FileInputStream;
90import java.io.FileNotFoundException;
91import java.io.FileOutputStream;
92import java.io.FileReader;
93import java.io.FilenameFilter;
94import java.io.IOException;
95import java.io.InputStream;
96import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -080097import java.security.NoSuchAlgorithmException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import java.util.ArrayList;
99import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -0700100import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import java.util.Collections;
102import java.util.Comparator;
103import java.util.Enumeration;
104import java.util.HashMap;
105import java.util.HashSet;
106import java.util.Iterator;
107import java.util.List;
108import java.util.Map;
109import java.util.Set;
110import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800111import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.util.zip.ZipFile;
113import java.util.zip.ZipOutputStream;
114
115class PackageManagerService extends IPackageManager.Stub {
116 private static final String TAG = "PackageManager";
117 private static final boolean DEBUG_SETTINGS = false;
118 private static final boolean DEBUG_PREFERRED = false;
119
120 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
121 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400122 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 private static final int FIRST_APPLICATION_UID =
124 Process.FIRST_APPLICATION_UID;
125 private static final int MAX_APPLICATION_UIDS = 1000;
126
127 private static final boolean SHOW_INFO = false;
128
129 private static final boolean GET_CERTIFICATES = true;
130
Oscar Montemayora8529f62009-11-18 10:14:20 -0800131 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final int REMOVE_EVENTS =
134 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
135 private static final int ADD_EVENTS =
136 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
137
138 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
139
140 static final int SCAN_MONITOR = 1<<0;
141 static final int SCAN_NO_DEX = 1<<1;
142 static final int SCAN_FORCE_DEX = 1<<2;
143 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800144 static final int SCAN_NEW_INSTALL = 1<<4;
145 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
147 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
148 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700149 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150
Dianne Hackborn851a5412009-05-08 12:06:44 -0700151 final int mSdkVersion = Build.VERSION.SDK_INT;
152 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
153 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 final Context mContext;
156 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700157 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 final DisplayMetrics mMetrics;
159 final int mDefParseFlags;
160 final String[] mSeparateProcesses;
161
162 // This is where all application persistent data goes.
163 final File mAppDataDir;
164
Oscar Montemayora8529f62009-11-18 10:14:20 -0800165 // If Encrypted File System feature is enabled, all application persistent data
166 // should go here instead.
167 final File mSecureAppDataDir;
168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 // This is the object monitoring the framework dir.
170 final FileObserver mFrameworkInstallObserver;
171
172 // This is the object monitoring the system app dir.
173 final FileObserver mSystemInstallObserver;
174
175 // This is the object monitoring mAppInstallDir.
176 final FileObserver mAppInstallObserver;
177
178 // This is the object monitoring mDrmAppPrivateInstallDir.
179 final FileObserver mDrmAppInstallObserver;
180
181 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
182 // LOCK HELD. Can be called with mInstallLock held.
183 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 final File mFrameworkDir;
186 final File mSystemAppDir;
187 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700188 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
191 // apps.
192 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 // Lock for state used when installing and doing other long running
197 // operations. Methods that must be called with this lock held have
198 // the prefix "LI".
199 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 // These are the directories in the 3rd party applications installed dir
202 // that we have currently loaded packages from. Keys are the application's
203 // installed zip file (absolute codePath), and values are Package.
204 final HashMap<String, PackageParser.Package> mAppDirs =
205 new HashMap<String, PackageParser.Package>();
206
207 // Information for the parser to write more useful error messages.
208 File mScanningPath;
209 int mLastScanError;
210
211 final int[] mOutPermissions = new int[3];
212
213 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 // Keys are String (package name), values are Package. This also serves
216 // as the lock for the global state. Methods that must be called with
217 // this lock held have the prefix "LP".
218 final HashMap<String, PackageParser.Package> mPackages =
219 new HashMap<String, PackageParser.Package>();
220
221 final Settings mSettings;
222 boolean mRestoredSettings;
223 boolean mReportedUidError;
224
225 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
226 int[] mGlobalGids;
227
228 // These are the built-in uid -> permission mappings that were read from the
229 // etc/permissions.xml file.
230 final SparseArray<HashSet<String>> mSystemPermissions =
231 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 // These are the built-in shared libraries that were read from the
234 // etc/permissions.xml file.
235 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800236
Dianne Hackborn49237342009-08-27 20:08:01 -0700237 // Temporary for building the final shared libraries for an .apk.
238 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800239
Dianne Hackborn49237342009-08-27 20:08:01 -0700240 // These are the features this devices supports that were read from the
241 // etc/permissions.xml file.
242 final HashMap<String, FeatureInfo> mAvailableFeatures =
243 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 // All available activities, for your resolving pleasure.
246 final ActivityIntentResolver mActivities =
247 new ActivityIntentResolver();
248
249 // All available receivers, for your resolving pleasure.
250 final ActivityIntentResolver mReceivers =
251 new ActivityIntentResolver();
252
253 // All available services, for your resolving pleasure.
254 final ServiceIntentResolver mServices = new ServiceIntentResolver();
255
256 // Keys are String (provider class name), values are Provider.
257 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
258 new HashMap<ComponentName, PackageParser.Provider>();
259
260 // Mapping from provider base names (first directory in content URI codePath)
261 // to the provider information.
262 final HashMap<String, PackageParser.Provider> mProviders =
263 new HashMap<String, PackageParser.Provider>();
264
265 // Mapping from instrumentation class names to info about them.
266 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
267 new HashMap<ComponentName, PackageParser.Instrumentation>();
268
269 // Mapping from permission names to info about them.
270 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
271 new HashMap<String, PackageParser.PermissionGroup>();
272
Dianne Hackborn854060af2009-07-09 18:14:31 -0700273 // Broadcast actions that are only available to the system.
274 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 boolean mSystemReady;
277 boolean mSafeMode;
278 boolean mHasSystemUidErrors;
279
280 ApplicationInfo mAndroidApplication;
281 final ActivityInfo mResolveActivity = new ActivityInfo();
282 final ResolveInfo mResolveInfo = new ResolveInfo();
283 ComponentName mResolveComponentName;
284 PackageParser.Package mPlatformPackage;
285
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700286 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800287 final HashMap<String, ArrayList<String>> mPendingBroadcasts
288 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700289 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800290 static final int MCS_BOUND = 3;
291 static final int END_COPY = 4;
292 static final int INIT_COPY = 5;
293 static final int MCS_UNBIND = 6;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700294 // Delay time in millisecs
295 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800296 private ServiceConnection mDefContainerConn = new ServiceConnection() {
297 public void onServiceConnected(ComponentName name, IBinder service) {
298 IMediaContainerService imcs =
299 IMediaContainerService.Stub.asInterface(service);
300 Message msg = mHandler.obtainMessage(MCS_BOUND, imcs);
301 mHandler.sendMessage(msg);
302 }
303
304 public void onServiceDisconnected(ComponentName name) {
305 }
306 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700307
308 class PackageHandler extends Handler {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800309 final ArrayList<InstallArgs> mPendingInstalls =
310 new ArrayList<InstallArgs>();
311 // Service Connection to remote media container service to copy
312 // package uri's from external media onto secure containers
313 // or internal storage.
314 private IMediaContainerService mContainerService = null;
315
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700316 PackageHandler(Looper looper) {
317 super(looper);
318 }
319 public void handleMessage(Message msg) {
320 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800321 case INIT_COPY: {
322 InstallArgs args = (InstallArgs) msg.obj;
323 args.createCopyFile();
324 Intent service = new Intent().setComponent(new ComponentName(
325 "com.android.defcontainer",
326 "com.android.defcontainer.DefaultContainerService"));
327 if (mContainerService != null) {
328 // No need to add to pending list. Use remote stub directly
329 handleStartCopy(args);
330 } else {
331 if (mContext.bindService(service, mDefContainerConn,
332 Context.BIND_AUTO_CREATE)) {
333 mPendingInstalls.add(args);
334 } else {
335 Log.e(TAG, "Failed to bind to media container service");
336 // Indicate install failure TODO add new error code
337 processPendingInstall(args,
338 PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800339 }
340 }
341 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800342 }
343 case MCS_BOUND: {
344 // Initialize mContainerService if needed.
345 if (msg.obj != null) {
346 mContainerService = (IMediaContainerService) msg.obj;
347 }
348 if (mPendingInstalls.size() > 0) {
349 InstallArgs args = mPendingInstalls.remove(0);
350 if (args != null) {
351 handleStartCopy(args);
352 }
353 }
354 break;
355 }
356 case MCS_UNBIND : {
357 if (mPendingInstalls.size() == 0) {
358 mContext.unbindService(mDefContainerConn);
359 mContainerService = null;
360 }
361 break;
362 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700363 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800364 String packages[];
365 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700366 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700367 int uids[];
368 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800369 if (mPendingBroadcasts == null) {
370 return;
371 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700372 size = mPendingBroadcasts.size();
373 if (size <= 0) {
374 // Nothing to be done. Just return
375 return;
376 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800377 packages = new String[size];
378 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700379 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800380 Iterator<HashMap.Entry<String, ArrayList<String>>>
381 it = mPendingBroadcasts.entrySet().iterator();
382 int i = 0;
383 while (it.hasNext() && i < size) {
384 HashMap.Entry<String, ArrayList<String>> ent = it.next();
385 packages[i] = ent.getKey();
386 components[i] = ent.getValue();
387 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700388 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800389 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700390 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800391 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700392 mPendingBroadcasts.clear();
393 }
394 // Send broadcasts
395 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800396 sendPackageChangedBroadcast(packages[i], true,
397 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700398 }
399 break;
400 }
401 }
402 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800403
404 // Utility method to initiate copying apk via media
405 // container service.
406 private void handleStartCopy(InstallArgs args) {
407 int ret = PackageManager.INSTALL_SUCCEEDED;
408 if (mContainerService == null) {
409 // Install error
410 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
411 } else {
412 ret = args.copyApk(mContainerService);
413 }
414 mHandler.sendEmptyMessage(MCS_UNBIND);
415 processPendingInstall(args, ret);
416 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700417 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800418
419 static boolean installOnSd(int flags) {
420 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
421 ((flags & PackageManager.INSTALL_ON_SDCARD) == 0)) {
422 return false;
423 }
424 return true;
425 }
426
427 static boolean isFwdLocked(int flags) {
428 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
429 return true;
430 }
431 return false;
432 }
433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 public static final IPackageManager main(Context context, boolean factoryTest) {
435 PackageManagerService m = new PackageManagerService(context, factoryTest);
436 ServiceManager.addService("package", m);
437 return m;
438 }
439
440 static String[] splitString(String str, char sep) {
441 int count = 1;
442 int i = 0;
443 while ((i=str.indexOf(sep, i)) >= 0) {
444 count++;
445 i++;
446 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 String[] res = new String[count];
449 i=0;
450 count = 0;
451 int lastI=0;
452 while ((i=str.indexOf(sep, i)) >= 0) {
453 res[count] = str.substring(lastI, i);
454 count++;
455 i++;
456 lastI = i;
457 }
458 res[count] = str.substring(lastI, str.length());
459 return res;
460 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800463 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 if (mSdkVersion <= 0) {
467 Log.w(TAG, "**** ro.build.version.sdk not set!");
468 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 mContext = context;
471 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700472 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 mMetrics = new DisplayMetrics();
474 mSettings = new Settings();
475 mSettings.addSharedUserLP("android.uid.system",
476 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
477 mSettings.addSharedUserLP("android.uid.phone",
478 MULTIPLE_APPLICATION_UIDS
479 ? RADIO_UID : FIRST_APPLICATION_UID,
480 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400481 mSettings.addSharedUserLP("android.uid.log",
482 MULTIPLE_APPLICATION_UIDS
483 ? LOG_UID : FIRST_APPLICATION_UID,
484 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485
486 String separateProcesses = SystemProperties.get("debug.separate_processes");
487 if (separateProcesses != null && separateProcesses.length() > 0) {
488 if ("*".equals(separateProcesses)) {
489 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
490 mSeparateProcesses = null;
491 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
492 } else {
493 mDefParseFlags = 0;
494 mSeparateProcesses = separateProcesses.split(",");
495 Log.w(TAG, "Running with debug.separate_processes: "
496 + separateProcesses);
497 }
498 } else {
499 mDefParseFlags = 0;
500 mSeparateProcesses = null;
501 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 Installer installer = new Installer();
504 // Little hacky thing to check if installd is here, to determine
505 // whether we are running on the simulator and thus need to take
506 // care of building the /data file structure ourself.
507 // (apparently the sim now has a working installer)
508 if (installer.ping() && Process.supportsProcesses()) {
509 mInstaller = installer;
510 } else {
511 mInstaller = null;
512 }
513
514 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
515 Display d = wm.getDefaultDisplay();
516 d.getMetrics(mMetrics);
517
518 synchronized (mInstallLock) {
519 synchronized (mPackages) {
520 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700521 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 File dataDir = Environment.getDataDirectory();
524 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800525 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
527
528 if (mInstaller == null) {
529 // Make sure these dirs exist, when we are running in
530 // the simulator.
531 // Make a wide-open directory for random misc stuff.
532 File miscDir = new File(dataDir, "misc");
533 miscDir.mkdirs();
534 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800535 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 mDrmAppPrivateInstallDir.mkdirs();
537 }
538
539 readPermissions();
540
541 mRestoredSettings = mSettings.readLP();
542 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800543
544 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800546
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800547 // Set flag to monitor and not change apk file paths when
548 // scanning install directories.
549 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700550 if (mNoDexOpt) {
551 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800552 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700553 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700558 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700561 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 /**
564 * Out of paranoia, ensure that everything in the boot class
565 * path has been dexed.
566 */
567 String bootClassPath = System.getProperty("java.boot.class.path");
568 if (bootClassPath != null) {
569 String[] paths = splitString(bootClassPath, ':');
570 for (int i=0; i<paths.length; i++) {
571 try {
572 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
573 libFiles.add(paths[i]);
574 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700575 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 }
577 } catch (FileNotFoundException e) {
578 Log.w(TAG, "Boot class path not found: " + paths[i]);
579 } catch (IOException e) {
580 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
581 }
582 }
583 } else {
584 Log.w(TAG, "No BOOTCLASSPATH found!");
585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 /**
588 * Also ensure all external libraries have had dexopt run on them.
589 */
590 if (mSharedLibraries.size() > 0) {
591 Iterator<String> libs = mSharedLibraries.values().iterator();
592 while (libs.hasNext()) {
593 String lib = libs.next();
594 try {
595 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
596 libFiles.add(lib);
597 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700598 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 }
600 } catch (FileNotFoundException e) {
601 Log.w(TAG, "Library not found: " + lib);
602 } catch (IOException e) {
603 Log.w(TAG, "Exception reading library: " + lib, e);
604 }
605 }
606 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 // Gross hack for now: we know this file doesn't contain any
609 // code, so don't dexopt it to avoid the resulting log spew.
610 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 /**
613 * And there are a number of commands implemented in Java, which
614 * we currently need to do the dexopt on so that they can be
615 * run from a non-root shell.
616 */
617 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700618 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 for (int i=0; i<frameworkFiles.length; i++) {
620 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
621 String path = libPath.getPath();
622 // Skip the file if we alrady did it.
623 if (libFiles.contains(path)) {
624 continue;
625 }
626 // Skip the file if it is not a type we want to dexopt.
627 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
628 continue;
629 }
630 try {
631 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
632 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700633 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 }
635 } catch (FileNotFoundException e) {
636 Log.w(TAG, "Jar not found: " + path);
637 } catch (IOException e) {
638 Log.w(TAG, "Exception reading jar: " + path, e);
639 }
640 }
641 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800642
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700643 if (didDexOpt) {
644 // If we had to do a dexopt of one of the previous
645 // things, then something on the system has changed.
646 // Consider this significant, and wipe away all other
647 // existing dexopt files to ensure we don't leave any
648 // dangling around.
649 String[] files = mDalvikCacheDir.list();
650 if (files != null) {
651 for (int i=0; i<files.length; i++) {
652 String fn = files[i];
653 if (fn.startsWith("data@app@")
654 || fn.startsWith("data@app-private@")) {
655 Log.i(TAG, "Pruning dalvik file: " + fn);
656 (new File(mDalvikCacheDir, fn)).delete();
657 }
658 }
659 }
660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 mFrameworkInstallObserver = new AppDirObserver(
664 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
665 mFrameworkInstallObserver.startWatching();
666 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800667 scanMode | SCAN_NO_DEX);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
669 mSystemInstallObserver = new AppDirObserver(
670 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
671 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800672 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 mAppInstallDir = new File(dataDir, "app");
674 if (mInstaller == null) {
675 // Make sure these dirs exist, when we are running in
676 // the simulator.
677 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
678 }
679 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800680 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 //clean up list
682 for(int i = 0; i < deletePkgsList.size(); i++) {
683 //clean up here
684 cleanupInstallFailedPackage(deletePkgsList.get(i));
685 }
686 //delete tmp files
687 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800688
689 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 SystemClock.uptimeMillis());
691 mAppInstallObserver = new AppDirObserver(
692 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
693 mAppInstallObserver.startWatching();
694 scanDirLI(mAppInstallDir, 0, scanMode);
695
696 mDrmAppInstallObserver = new AppDirObserver(
697 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
698 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800699 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800701 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 SystemClock.uptimeMillis());
703 Log.i(TAG, "Time to scan packages: "
704 + ((SystemClock.uptimeMillis()-startTime)/1000f)
705 + " seconds");
706
707 updatePermissionsLP();
708
709 mSettings.writeLP();
710
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800711 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 // Now after opening every single application zip, make sure they
715 // are all flushed. Not really needed, but keeps things nice and
716 // tidy.
717 Runtime.getRuntime().gc();
718 } // synchronized (mPackages)
719 } // synchronized (mInstallLock)
720 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 @Override
723 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
724 throws RemoteException {
725 try {
726 return super.onTransact(code, data, reply, flags);
727 } catch (RuntimeException e) {
728 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
729 Log.e(TAG, "Package Manager Crash", e);
730 }
731 throw e;
732 }
733 }
734
Dianne Hackborne6620b22010-01-22 14:46:21 -0800735 void cleanupInstallFailedPackage(PackageSetting ps) {
736 Log.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 if (mInstaller != null) {
Kenny Rootbdbc9252010-01-28 12:03:49 -0800738 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
739 int retCode = mInstaller.remove(ps.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 if (retCode < 0) {
741 Log.w(TAG, "Couldn't remove app data directory for package: "
Dianne Hackborne6620b22010-01-22 14:46:21 -0800742 + ps.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 }
744 } else {
745 //for emulator
Dianne Hackborne6620b22010-01-22 14:46:21 -0800746 PackageParser.Package pkg = mPackages.get(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 File dataDir = new File(pkg.applicationInfo.dataDir);
748 dataDir.delete();
749 }
Dianne Hackborne6620b22010-01-22 14:46:21 -0800750 if (ps.codePath != null) {
751 if (!ps.codePath.delete()) {
752 Log.w(TAG, "Unable to remove old code file: " + ps.codePath);
753 }
754 }
755 if (ps.resourcePath != null) {
756 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) {
757 Log.w(TAG, "Unable to remove old code file: " + ps.resourcePath);
758 }
759 }
760 mSettings.removePackageLP(ps.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 }
762
763 void readPermissions() {
764 // Read permissions from .../etc/permission directory.
765 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
766 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
767 Log.w(TAG, "No directory " + libraryDir + ", skipping");
768 return;
769 }
770 if (!libraryDir.canRead()) {
771 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
772 return;
773 }
774
775 // Iterate over the files in the directory and scan .xml files
776 for (File f : libraryDir.listFiles()) {
777 // We'll read platform.xml last
778 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
779 continue;
780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 if (!f.getPath().endsWith(".xml")) {
783 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
784 continue;
785 }
786 if (!f.canRead()) {
787 Log.w(TAG, "Permissions library file " + f + " cannot be read");
788 continue;
789 }
790
791 readPermissionsFromXml(f);
792 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
795 final File permFile = new File(Environment.getRootDirectory(),
796 "etc/permissions/platform.xml");
797 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800798
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700799 StringBuilder sb = new StringBuilder(128);
800 sb.append("Libs:");
801 Iterator<String> it = mSharedLibraries.keySet().iterator();
802 while (it.hasNext()) {
803 sb.append(' ');
804 String name = it.next();
805 sb.append(name);
806 sb.append(':');
807 sb.append(mSharedLibraries.get(name));
808 }
809 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800810
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700811 sb.setLength(0);
812 sb.append("Features:");
813 it = mAvailableFeatures.keySet().iterator();
814 while (it.hasNext()) {
815 sb.append(' ');
816 sb.append(it.next());
817 }
818 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800820
821 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 FileReader permReader = null;
823 try {
824 permReader = new FileReader(permFile);
825 } catch (FileNotFoundException e) {
826 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
827 return;
828 }
829
830 try {
831 XmlPullParser parser = Xml.newPullParser();
832 parser.setInput(permReader);
833
834 XmlUtils.beginDocument(parser, "permissions");
835
836 while (true) {
837 XmlUtils.nextElement(parser);
838 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
839 break;
840 }
841
842 String name = parser.getName();
843 if ("group".equals(name)) {
844 String gidStr = parser.getAttributeValue(null, "gid");
845 if (gidStr != null) {
846 int gid = Integer.parseInt(gidStr);
847 mGlobalGids = appendInt(mGlobalGids, gid);
848 } else {
849 Log.w(TAG, "<group> without gid at "
850 + parser.getPositionDescription());
851 }
852
853 XmlUtils.skipCurrentTag(parser);
854 continue;
855 } else if ("permission".equals(name)) {
856 String perm = parser.getAttributeValue(null, "name");
857 if (perm == null) {
858 Log.w(TAG, "<permission> without name at "
859 + parser.getPositionDescription());
860 XmlUtils.skipCurrentTag(parser);
861 continue;
862 }
863 perm = perm.intern();
864 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 } else if ("assign-permission".equals(name)) {
867 String perm = parser.getAttributeValue(null, "name");
868 if (perm == null) {
869 Log.w(TAG, "<assign-permission> without name at "
870 + parser.getPositionDescription());
871 XmlUtils.skipCurrentTag(parser);
872 continue;
873 }
874 String uidStr = parser.getAttributeValue(null, "uid");
875 if (uidStr == null) {
876 Log.w(TAG, "<assign-permission> without uid at "
877 + parser.getPositionDescription());
878 XmlUtils.skipCurrentTag(parser);
879 continue;
880 }
881 int uid = Process.getUidForName(uidStr);
882 if (uid < 0) {
883 Log.w(TAG, "<assign-permission> with unknown uid \""
884 + uidStr + "\" at "
885 + parser.getPositionDescription());
886 XmlUtils.skipCurrentTag(parser);
887 continue;
888 }
889 perm = perm.intern();
890 HashSet<String> perms = mSystemPermissions.get(uid);
891 if (perms == null) {
892 perms = new HashSet<String>();
893 mSystemPermissions.put(uid, perms);
894 }
895 perms.add(perm);
896 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 } else if ("library".equals(name)) {
899 String lname = parser.getAttributeValue(null, "name");
900 String lfile = parser.getAttributeValue(null, "file");
901 if (lname == null) {
902 Log.w(TAG, "<library> without name at "
903 + parser.getPositionDescription());
904 } else if (lfile == null) {
905 Log.w(TAG, "<library> without file at "
906 + parser.getPositionDescription());
907 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700908 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700909 mSharedLibraries.put(lname, lfile);
910 }
911 XmlUtils.skipCurrentTag(parser);
912 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800913
Dianne Hackborn49237342009-08-27 20:08:01 -0700914 } else if ("feature".equals(name)) {
915 String fname = parser.getAttributeValue(null, "name");
916 if (fname == null) {
917 Log.w(TAG, "<feature> without name at "
918 + parser.getPositionDescription());
919 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700920 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700921 FeatureInfo fi = new FeatureInfo();
922 fi.name = fname;
923 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 }
925 XmlUtils.skipCurrentTag(parser);
926 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 } else {
929 XmlUtils.skipCurrentTag(parser);
930 continue;
931 }
932
933 }
934 } catch (XmlPullParserException e) {
935 Log.w(TAG, "Got execption parsing permissions.", e);
936 } catch (IOException e) {
937 Log.w(TAG, "Got execption parsing permissions.", e);
938 }
939 }
940
941 void readPermission(XmlPullParser parser, String name)
942 throws IOException, XmlPullParserException {
943
944 name = name.intern();
945
946 BasePermission bp = mSettings.mPermissions.get(name);
947 if (bp == null) {
948 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
949 mSettings.mPermissions.put(name, bp);
950 }
951 int outerDepth = parser.getDepth();
952 int type;
953 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
954 && (type != XmlPullParser.END_TAG
955 || parser.getDepth() > outerDepth)) {
956 if (type == XmlPullParser.END_TAG
957 || type == XmlPullParser.TEXT) {
958 continue;
959 }
960
961 String tagName = parser.getName();
962 if ("group".equals(tagName)) {
963 String gidStr = parser.getAttributeValue(null, "gid");
964 if (gidStr != null) {
965 int gid = Process.getGidForName(gidStr);
966 bp.gids = appendInt(bp.gids, gid);
967 } else {
968 Log.w(TAG, "<group> without gid at "
969 + parser.getPositionDescription());
970 }
971 }
972 XmlUtils.skipCurrentTag(parser);
973 }
974 }
975
976 static int[] appendInt(int[] cur, int val) {
977 if (cur == null) {
978 return new int[] { val };
979 }
980 final int N = cur.length;
981 for (int i=0; i<N; i++) {
982 if (cur[i] == val) {
983 return cur;
984 }
985 }
986 int[] ret = new int[N+1];
987 System.arraycopy(cur, 0, ret, 0, N);
988 ret[N] = val;
989 return ret;
990 }
991
992 static int[] appendInts(int[] cur, int[] add) {
993 if (add == null) return cur;
994 if (cur == null) return add;
995 final int N = add.length;
996 for (int i=0; i<N; i++) {
997 cur = appendInt(cur, add[i]);
998 }
999 return cur;
1000 }
1001
1002 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -07001003 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1004 // The package has been uninstalled but has retained data and resources.
1005 return PackageParser.generatePackageInfo(p, null, flags);
1006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 final PackageSetting ps = (PackageSetting)p.mExtras;
1008 if (ps == null) {
1009 return null;
1010 }
1011 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
1012 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1013 }
1014
1015 public PackageInfo getPackageInfo(String packageName, int flags) {
1016 synchronized (mPackages) {
1017 PackageParser.Package p = mPackages.get(packageName);
1018 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001019 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 + ": " + p);
1021 if (p != null) {
1022 return generatePackageInfo(p, flags);
1023 }
1024 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1025 return generatePackageInfoFromSettingsLP(packageName, flags);
1026 }
1027 }
1028 return null;
1029 }
1030
1031 public int getPackageUid(String packageName) {
1032 synchronized (mPackages) {
1033 PackageParser.Package p = mPackages.get(packageName);
1034 if(p != null) {
1035 return p.applicationInfo.uid;
1036 }
1037 PackageSetting ps = mSettings.mPackages.get(packageName);
1038 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1039 return -1;
1040 }
1041 p = ps.pkg;
1042 return p != null ? p.applicationInfo.uid : -1;
1043 }
1044 }
1045
1046 public int[] getPackageGids(String packageName) {
1047 synchronized (mPackages) {
1048 PackageParser.Package p = mPackages.get(packageName);
1049 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001050 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 + ": " + p);
1052 if (p != null) {
1053 final PackageSetting ps = (PackageSetting)p.mExtras;
1054 final SharedUserSetting suid = ps.sharedUser;
1055 return suid != null ? suid.gids : ps.gids;
1056 }
1057 }
1058 // stupid thing to indicate an error.
1059 return new int[0];
1060 }
1061
1062 public PermissionInfo getPermissionInfo(String name, int flags) {
1063 synchronized (mPackages) {
1064 final BasePermission p = mSettings.mPermissions.get(name);
1065 if (p != null && p.perm != null) {
1066 return PackageParser.generatePermissionInfo(p.perm, flags);
1067 }
1068 return null;
1069 }
1070 }
1071
1072 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1073 synchronized (mPackages) {
1074 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1075 for (BasePermission p : mSettings.mPermissions.values()) {
1076 if (group == null) {
1077 if (p.perm.info.group == null) {
1078 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1079 }
1080 } else {
1081 if (group.equals(p.perm.info.group)) {
1082 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1083 }
1084 }
1085 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 if (out.size() > 0) {
1088 return out;
1089 }
1090 return mPermissionGroups.containsKey(group) ? out : null;
1091 }
1092 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1095 synchronized (mPackages) {
1096 return PackageParser.generatePermissionGroupInfo(
1097 mPermissionGroups.get(name), flags);
1098 }
1099 }
1100
1101 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1102 synchronized (mPackages) {
1103 final int N = mPermissionGroups.size();
1104 ArrayList<PermissionGroupInfo> out
1105 = new ArrayList<PermissionGroupInfo>(N);
1106 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1107 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1108 }
1109 return out;
1110 }
1111 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1114 PackageSetting ps = mSettings.mPackages.get(packageName);
1115 if(ps != null) {
1116 if(ps.pkg == null) {
1117 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1118 if(pInfo != null) {
1119 return pInfo.applicationInfo;
1120 }
1121 return null;
1122 }
1123 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1124 }
1125 return null;
1126 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1129 PackageSetting ps = mSettings.mPackages.get(packageName);
1130 if(ps != null) {
1131 if(ps.pkg == null) {
1132 ps.pkg = new PackageParser.Package(packageName);
1133 ps.pkg.applicationInfo.packageName = packageName;
1134 }
1135 return generatePackageInfo(ps.pkg, flags);
1136 }
1137 return null;
1138 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1141 synchronized (mPackages) {
1142 PackageParser.Package p = mPackages.get(packageName);
1143 if (Config.LOGV) Log.v(
1144 TAG, "getApplicationInfo " + packageName
1145 + ": " + p);
1146 if (p != null) {
1147 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001148 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 }
1150 if ("android".equals(packageName)||"system".equals(packageName)) {
1151 return mAndroidApplication;
1152 }
1153 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1154 return generateApplicationInfoFromSettingsLP(packageName, flags);
1155 }
1156 }
1157 return null;
1158 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001159
1160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1162 mContext.enforceCallingOrSelfPermission(
1163 android.Manifest.permission.CLEAR_APP_CACHE, null);
1164 // Queue up an async operation since clearing cache may take a little while.
1165 mHandler.post(new Runnable() {
1166 public void run() {
1167 mHandler.removeCallbacks(this);
1168 int retCode = -1;
1169 if (mInstaller != null) {
1170 retCode = mInstaller.freeCache(freeStorageSize);
1171 if (retCode < 0) {
1172 Log.w(TAG, "Couldn't clear application caches");
1173 }
1174 } //end if mInstaller
1175 if (observer != null) {
1176 try {
1177 observer.onRemoveCompleted(null, (retCode >= 0));
1178 } catch (RemoteException e) {
1179 Log.w(TAG, "RemoveException when invoking call back");
1180 }
1181 }
1182 }
1183 });
1184 }
1185
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001186 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001187 mContext.enforceCallingOrSelfPermission(
1188 android.Manifest.permission.CLEAR_APP_CACHE, null);
1189 // Queue up an async operation since clearing cache may take a little while.
1190 mHandler.post(new Runnable() {
1191 public void run() {
1192 mHandler.removeCallbacks(this);
1193 int retCode = -1;
1194 if (mInstaller != null) {
1195 retCode = mInstaller.freeCache(freeStorageSize);
1196 if (retCode < 0) {
1197 Log.w(TAG, "Couldn't clear application caches");
1198 }
1199 }
1200 if(pi != null) {
1201 try {
1202 // Callback via pending intent
1203 int code = (retCode >= 0) ? 1 : 0;
1204 pi.sendIntent(null, code, null,
1205 null, null);
1206 } catch (SendIntentException e1) {
1207 Log.i(TAG, "Failed to send pending intent");
1208 }
1209 }
1210 }
1211 });
1212 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1215 synchronized (mPackages) {
1216 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001217
1218 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001220 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 }
1222 if (mResolveComponentName.equals(component)) {
1223 return mResolveActivity;
1224 }
1225 }
1226 return null;
1227 }
1228
1229 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1230 synchronized (mPackages) {
1231 PackageParser.Activity a = mReceivers.mActivities.get(component);
1232 if (Config.LOGV) Log.v(
1233 TAG, "getReceiverInfo " + component + ": " + a);
1234 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1235 return PackageParser.generateActivityInfo(a, flags);
1236 }
1237 }
1238 return null;
1239 }
1240
1241 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1242 synchronized (mPackages) {
1243 PackageParser.Service s = mServices.mServices.get(component);
1244 if (Config.LOGV) Log.v(
1245 TAG, "getServiceInfo " + component + ": " + s);
1246 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1247 return PackageParser.generateServiceInfo(s, flags);
1248 }
1249 }
1250 return null;
1251 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 public String[] getSystemSharedLibraryNames() {
1254 Set<String> libSet;
1255 synchronized (mPackages) {
1256 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001257 int size = libSet.size();
1258 if (size > 0) {
1259 String[] libs = new String[size];
1260 libSet.toArray(libs);
1261 return libs;
1262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001264 return null;
1265 }
1266
1267 public FeatureInfo[] getSystemAvailableFeatures() {
1268 Collection<FeatureInfo> featSet;
1269 synchronized (mPackages) {
1270 featSet = mAvailableFeatures.values();
1271 int size = featSet.size();
1272 if (size > 0) {
1273 FeatureInfo[] features = new FeatureInfo[size+1];
1274 featSet.toArray(features);
1275 FeatureInfo fi = new FeatureInfo();
1276 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1277 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1278 features[size] = fi;
1279 return features;
1280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 }
1282 return null;
1283 }
1284
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001285 public boolean hasSystemFeature(String name) {
1286 synchronized (mPackages) {
1287 return mAvailableFeatures.containsKey(name);
1288 }
1289 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 public int checkPermission(String permName, String pkgName) {
1292 synchronized (mPackages) {
1293 PackageParser.Package p = mPackages.get(pkgName);
1294 if (p != null && p.mExtras != null) {
1295 PackageSetting ps = (PackageSetting)p.mExtras;
1296 if (ps.sharedUser != null) {
1297 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1298 return PackageManager.PERMISSION_GRANTED;
1299 }
1300 } else if (ps.grantedPermissions.contains(permName)) {
1301 return PackageManager.PERMISSION_GRANTED;
1302 }
1303 }
1304 }
1305 return PackageManager.PERMISSION_DENIED;
1306 }
1307
1308 public int checkUidPermission(String permName, int uid) {
1309 synchronized (mPackages) {
1310 Object obj = mSettings.getUserIdLP(uid);
1311 if (obj != null) {
1312 if (obj instanceof SharedUserSetting) {
1313 SharedUserSetting sus = (SharedUserSetting)obj;
1314 if (sus.grantedPermissions.contains(permName)) {
1315 return PackageManager.PERMISSION_GRANTED;
1316 }
1317 } else if (obj instanceof PackageSetting) {
1318 PackageSetting ps = (PackageSetting)obj;
1319 if (ps.grantedPermissions.contains(permName)) {
1320 return PackageManager.PERMISSION_GRANTED;
1321 }
1322 }
1323 } else {
1324 HashSet<String> perms = mSystemPermissions.get(uid);
1325 if (perms != null && perms.contains(permName)) {
1326 return PackageManager.PERMISSION_GRANTED;
1327 }
1328 }
1329 }
1330 return PackageManager.PERMISSION_DENIED;
1331 }
1332
1333 private BasePermission findPermissionTreeLP(String permName) {
1334 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1335 if (permName.startsWith(bp.name) &&
1336 permName.length() > bp.name.length() &&
1337 permName.charAt(bp.name.length()) == '.') {
1338 return bp;
1339 }
1340 }
1341 return null;
1342 }
1343
1344 private BasePermission checkPermissionTreeLP(String permName) {
1345 if (permName != null) {
1346 BasePermission bp = findPermissionTreeLP(permName);
1347 if (bp != null) {
1348 if (bp.uid == Binder.getCallingUid()) {
1349 return bp;
1350 }
1351 throw new SecurityException("Calling uid "
1352 + Binder.getCallingUid()
1353 + " is not allowed to add to permission tree "
1354 + bp.name + " owned by uid " + bp.uid);
1355 }
1356 }
1357 throw new SecurityException("No permission tree found for " + permName);
1358 }
1359
1360 public boolean addPermission(PermissionInfo info) {
1361 synchronized (mPackages) {
1362 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1363 throw new SecurityException("Label must be specified in permission");
1364 }
1365 BasePermission tree = checkPermissionTreeLP(info.name);
1366 BasePermission bp = mSettings.mPermissions.get(info.name);
1367 boolean added = bp == null;
1368 if (added) {
1369 bp = new BasePermission(info.name, tree.sourcePackage,
1370 BasePermission.TYPE_DYNAMIC);
1371 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1372 throw new SecurityException(
1373 "Not allowed to modify non-dynamic permission "
1374 + info.name);
1375 }
1376 bp.perm = new PackageParser.Permission(tree.perm.owner,
1377 new PermissionInfo(info));
1378 bp.perm.info.packageName = tree.perm.info.packageName;
1379 bp.uid = tree.uid;
1380 if (added) {
1381 mSettings.mPermissions.put(info.name, bp);
1382 }
1383 mSettings.writeLP();
1384 return added;
1385 }
1386 }
1387
1388 public void removePermission(String name) {
1389 synchronized (mPackages) {
1390 checkPermissionTreeLP(name);
1391 BasePermission bp = mSettings.mPermissions.get(name);
1392 if (bp != null) {
1393 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1394 throw new SecurityException(
1395 "Not allowed to modify non-dynamic permission "
1396 + name);
1397 }
1398 mSettings.mPermissions.remove(name);
1399 mSettings.writeLP();
1400 }
1401 }
1402 }
1403
Dianne Hackborn854060af2009-07-09 18:14:31 -07001404 public boolean isProtectedBroadcast(String actionName) {
1405 synchronized (mPackages) {
1406 return mProtectedBroadcasts.contains(actionName);
1407 }
1408 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 public int checkSignatures(String pkg1, String pkg2) {
1411 synchronized (mPackages) {
1412 PackageParser.Package p1 = mPackages.get(pkg1);
1413 PackageParser.Package p2 = mPackages.get(pkg2);
1414 if (p1 == null || p1.mExtras == null
1415 || p2 == null || p2.mExtras == null) {
1416 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1417 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001418 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 }
1420 }
1421
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001422 public int checkUidSignatures(int uid1, int uid2) {
1423 synchronized (mPackages) {
1424 Signature[] s1;
1425 Signature[] s2;
1426 Object obj = mSettings.getUserIdLP(uid1);
1427 if (obj != null) {
1428 if (obj instanceof SharedUserSetting) {
1429 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1430 } else if (obj instanceof PackageSetting) {
1431 s1 = ((PackageSetting)obj).signatures.mSignatures;
1432 } else {
1433 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1434 }
1435 } else {
1436 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1437 }
1438 obj = mSettings.getUserIdLP(uid2);
1439 if (obj != null) {
1440 if (obj instanceof SharedUserSetting) {
1441 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1442 } else if (obj instanceof PackageSetting) {
1443 s2 = ((PackageSetting)obj).signatures.mSignatures;
1444 } else {
1445 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1446 }
1447 } else {
1448 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1449 }
1450 return checkSignaturesLP(s1, s2);
1451 }
1452 }
1453
1454 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1455 if (s1 == null) {
1456 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1458 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1459 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001460 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1462 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001463 final int N1 = s1.length;
1464 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 for (int i=0; i<N1; i++) {
1466 boolean match = false;
1467 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001468 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 match = true;
1470 break;
1471 }
1472 }
1473 if (!match) {
1474 return PackageManager.SIGNATURE_NO_MATCH;
1475 }
1476 }
1477 return PackageManager.SIGNATURE_MATCH;
1478 }
1479
1480 public String[] getPackagesForUid(int uid) {
1481 synchronized (mPackages) {
1482 Object obj = mSettings.getUserIdLP(uid);
1483 if (obj instanceof SharedUserSetting) {
1484 SharedUserSetting sus = (SharedUserSetting)obj;
1485 final int N = sus.packages.size();
1486 String[] res = new String[N];
1487 Iterator<PackageSetting> it = sus.packages.iterator();
1488 int i=0;
1489 while (it.hasNext()) {
1490 res[i++] = it.next().name;
1491 }
1492 return res;
1493 } else if (obj instanceof PackageSetting) {
1494 PackageSetting ps = (PackageSetting)obj;
1495 return new String[] { ps.name };
1496 }
1497 }
1498 return null;
1499 }
1500
1501 public String getNameForUid(int uid) {
1502 synchronized (mPackages) {
1503 Object obj = mSettings.getUserIdLP(uid);
1504 if (obj instanceof SharedUserSetting) {
1505 SharedUserSetting sus = (SharedUserSetting)obj;
1506 return sus.name + ":" + sus.userId;
1507 } else if (obj instanceof PackageSetting) {
1508 PackageSetting ps = (PackageSetting)obj;
1509 return ps.name;
1510 }
1511 }
1512 return null;
1513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 public int getUidForSharedUser(String sharedUserName) {
1516 if(sharedUserName == null) {
1517 return -1;
1518 }
1519 synchronized (mPackages) {
1520 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1521 if(suid == null) {
1522 return -1;
1523 }
1524 return suid.userId;
1525 }
1526 }
1527
1528 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1529 int flags) {
1530 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001531 return chooseBestActivity(intent, resolvedType, flags, query);
1532 }
1533
Mihai Predaeae850c2009-05-13 10:13:48 +02001534 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1535 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 if (query != null) {
1537 final int N = query.size();
1538 if (N == 1) {
1539 return query.get(0);
1540 } else if (N > 1) {
1541 // If there is more than one activity with the same priority,
1542 // then let the user decide between them.
1543 ResolveInfo r0 = query.get(0);
1544 ResolveInfo r1 = query.get(1);
1545 if (false) {
1546 System.out.println(r0.activityInfo.name +
1547 "=" + r0.priority + " vs " +
1548 r1.activityInfo.name +
1549 "=" + r1.priority);
1550 }
1551 // If the first activity has a higher priority, or a different
1552 // default, then it is always desireable to pick it.
1553 if (r0.priority != r1.priority
1554 || r0.preferredOrder != r1.preferredOrder
1555 || r0.isDefault != r1.isDefault) {
1556 return query.get(0);
1557 }
1558 // If we have saved a preference for a preferred activity for
1559 // this Intent, use that.
1560 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1561 flags, query, r0.priority);
1562 if (ri != null) {
1563 return ri;
1564 }
1565 return mResolveInfo;
1566 }
1567 }
1568 return null;
1569 }
1570
1571 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1572 int flags, List<ResolveInfo> query, int priority) {
1573 synchronized (mPackages) {
1574 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1575 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001576 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1578 if (prefs != null && prefs.size() > 0) {
1579 // First figure out how good the original match set is.
1580 // We will only allow preferred activities that came
1581 // from the same match quality.
1582 int match = 0;
1583 final int N = query.size();
1584 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1585 for (int j=0; j<N; j++) {
1586 ResolveInfo ri = query.get(j);
1587 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1588 + ": 0x" + Integer.toHexString(match));
1589 if (ri.match > match) match = ri.match;
1590 }
1591 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1592 + Integer.toHexString(match));
1593 match &= IntentFilter.MATCH_CATEGORY_MASK;
1594 final int M = prefs.size();
1595 for (int i=0; i<M; i++) {
1596 PreferredActivity pa = prefs.get(i);
1597 if (pa.mMatch != match) {
1598 continue;
1599 }
1600 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1601 if (DEBUG_PREFERRED) {
1602 Log.v(TAG, "Got preferred activity:");
1603 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1604 }
1605 if (ai != null) {
1606 for (int j=0; j<N; j++) {
1607 ResolveInfo ri = query.get(j);
1608 if (!ri.activityInfo.applicationInfo.packageName
1609 .equals(ai.applicationInfo.packageName)) {
1610 continue;
1611 }
1612 if (!ri.activityInfo.name.equals(ai.name)) {
1613 continue;
1614 }
1615
1616 // Okay we found a previously set preferred app.
1617 // If the result set is different from when this
1618 // was created, we need to clear it and re-ask the
1619 // user their preference.
1620 if (!pa.sameSet(query, priority)) {
1621 Log.i(TAG, "Result set changed, dropping preferred activity for "
1622 + intent + " type " + resolvedType);
1623 mSettings.mPreferredActivities.removeFilter(pa);
1624 return null;
1625 }
1626
1627 // Yay!
1628 return ri;
1629 }
1630 }
1631 }
1632 }
1633 }
1634 return null;
1635 }
1636
1637 public List<ResolveInfo> queryIntentActivities(Intent intent,
1638 String resolvedType, int flags) {
1639 ComponentName comp = intent.getComponent();
1640 if (comp != null) {
1641 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1642 ActivityInfo ai = getActivityInfo(comp, flags);
1643 if (ai != null) {
1644 ResolveInfo ri = new ResolveInfo();
1645 ri.activityInfo = ai;
1646 list.add(ri);
1647 }
1648 return list;
1649 }
1650
1651 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001652 String pkgName = intent.getPackage();
1653 if (pkgName == null) {
1654 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1655 resolvedType, flags);
1656 }
1657 PackageParser.Package pkg = mPackages.get(pkgName);
1658 if (pkg != null) {
1659 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1660 resolvedType, flags, pkg.activities);
1661 }
1662 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 }
1664 }
1665
1666 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1667 Intent[] specifics, String[] specificTypes, Intent intent,
1668 String resolvedType, int flags) {
1669 final String resultsAction = intent.getAction();
1670
1671 List<ResolveInfo> results = queryIntentActivities(
1672 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1673 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1674
1675 int specificsPos = 0;
1676 int N;
1677
1678 // todo: note that the algorithm used here is O(N^2). This
1679 // isn't a problem in our current environment, but if we start running
1680 // into situations where we have more than 5 or 10 matches then this
1681 // should probably be changed to something smarter...
1682
1683 // First we go through and resolve each of the specific items
1684 // that were supplied, taking care of removing any corresponding
1685 // duplicate items in the generic resolve list.
1686 if (specifics != null) {
1687 for (int i=0; i<specifics.length; i++) {
1688 final Intent sintent = specifics[i];
1689 if (sintent == null) {
1690 continue;
1691 }
1692
1693 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1694 String action = sintent.getAction();
1695 if (resultsAction != null && resultsAction.equals(action)) {
1696 // If this action was explicitly requested, then don't
1697 // remove things that have it.
1698 action = null;
1699 }
1700 ComponentName comp = sintent.getComponent();
1701 ResolveInfo ri = null;
1702 ActivityInfo ai = null;
1703 if (comp == null) {
1704 ri = resolveIntent(
1705 sintent,
1706 specificTypes != null ? specificTypes[i] : null,
1707 flags);
1708 if (ri == null) {
1709 continue;
1710 }
1711 if (ri == mResolveInfo) {
1712 // ACK! Must do something better with this.
1713 }
1714 ai = ri.activityInfo;
1715 comp = new ComponentName(ai.applicationInfo.packageName,
1716 ai.name);
1717 } else {
1718 ai = getActivityInfo(comp, flags);
1719 if (ai == null) {
1720 continue;
1721 }
1722 }
1723
1724 // Look for any generic query activities that are duplicates
1725 // of this specific one, and remove them from the results.
1726 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1727 N = results.size();
1728 int j;
1729 for (j=specificsPos; j<N; j++) {
1730 ResolveInfo sri = results.get(j);
1731 if ((sri.activityInfo.name.equals(comp.getClassName())
1732 && sri.activityInfo.applicationInfo.packageName.equals(
1733 comp.getPackageName()))
1734 || (action != null && sri.filter.matchAction(action))) {
1735 results.remove(j);
1736 if (Config.LOGV) Log.v(
1737 TAG, "Removing duplicate item from " + j
1738 + " due to specific " + specificsPos);
1739 if (ri == null) {
1740 ri = sri;
1741 }
1742 j--;
1743 N--;
1744 }
1745 }
1746
1747 // Add this specific item to its proper place.
1748 if (ri == null) {
1749 ri = new ResolveInfo();
1750 ri.activityInfo = ai;
1751 }
1752 results.add(specificsPos, ri);
1753 ri.specificIndex = i;
1754 specificsPos++;
1755 }
1756 }
1757
1758 // Now we go through the remaining generic results and remove any
1759 // duplicate actions that are found here.
1760 N = results.size();
1761 for (int i=specificsPos; i<N-1; i++) {
1762 final ResolveInfo rii = results.get(i);
1763 if (rii.filter == null) {
1764 continue;
1765 }
1766
1767 // Iterate over all of the actions of this result's intent
1768 // filter... typically this should be just one.
1769 final Iterator<String> it = rii.filter.actionsIterator();
1770 if (it == null) {
1771 continue;
1772 }
1773 while (it.hasNext()) {
1774 final String action = it.next();
1775 if (resultsAction != null && resultsAction.equals(action)) {
1776 // If this action was explicitly requested, then don't
1777 // remove things that have it.
1778 continue;
1779 }
1780 for (int j=i+1; j<N; j++) {
1781 final ResolveInfo rij = results.get(j);
1782 if (rij.filter != null && rij.filter.hasAction(action)) {
1783 results.remove(j);
1784 if (Config.LOGV) Log.v(
1785 TAG, "Removing duplicate item from " + j
1786 + " due to action " + action + " at " + i);
1787 j--;
1788 N--;
1789 }
1790 }
1791 }
1792
1793 // If the caller didn't request filter information, drop it now
1794 // so we don't have to marshall/unmarshall it.
1795 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1796 rii.filter = null;
1797 }
1798 }
1799
1800 // Filter out the caller activity if so requested.
1801 if (caller != null) {
1802 N = results.size();
1803 for (int i=0; i<N; i++) {
1804 ActivityInfo ainfo = results.get(i).activityInfo;
1805 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1806 && caller.getClassName().equals(ainfo.name)) {
1807 results.remove(i);
1808 break;
1809 }
1810 }
1811 }
1812
1813 // If the caller didn't request filter information,
1814 // drop them now so we don't have to
1815 // marshall/unmarshall it.
1816 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1817 N = results.size();
1818 for (int i=0; i<N; i++) {
1819 results.get(i).filter = null;
1820 }
1821 }
1822
1823 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1824 return results;
1825 }
1826
1827 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1828 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001829 ComponentName comp = intent.getComponent();
1830 if (comp != null) {
1831 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1832 ActivityInfo ai = getReceiverInfo(comp, flags);
1833 if (ai != null) {
1834 ResolveInfo ri = new ResolveInfo();
1835 ri.activityInfo = ai;
1836 list.add(ri);
1837 }
1838 return list;
1839 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001842 String pkgName = intent.getPackage();
1843 if (pkgName == null) {
1844 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1845 resolvedType, flags);
1846 }
1847 PackageParser.Package pkg = mPackages.get(pkgName);
1848 if (pkg != null) {
1849 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1850 resolvedType, flags, pkg.receivers);
1851 }
1852 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 }
1854 }
1855
1856 public ResolveInfo resolveService(Intent intent, String resolvedType,
1857 int flags) {
1858 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1859 flags);
1860 if (query != null) {
1861 if (query.size() >= 1) {
1862 // If there is more than one service with the same priority,
1863 // just arbitrarily pick the first one.
1864 return query.get(0);
1865 }
1866 }
1867 return null;
1868 }
1869
1870 public List<ResolveInfo> queryIntentServices(Intent intent,
1871 String resolvedType, int flags) {
1872 ComponentName comp = intent.getComponent();
1873 if (comp != null) {
1874 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1875 ServiceInfo si = getServiceInfo(comp, flags);
1876 if (si != null) {
1877 ResolveInfo ri = new ResolveInfo();
1878 ri.serviceInfo = si;
1879 list.add(ri);
1880 }
1881 return list;
1882 }
1883
1884 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001885 String pkgName = intent.getPackage();
1886 if (pkgName == null) {
1887 return (List<ResolveInfo>)mServices.queryIntent(intent,
1888 resolvedType, flags);
1889 }
1890 PackageParser.Package pkg = mPackages.get(pkgName);
1891 if (pkg != null) {
1892 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1893 resolvedType, flags, pkg.services);
1894 }
1895 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 }
1897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 public List<PackageInfo> getInstalledPackages(int flags) {
1900 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1901
1902 synchronized (mPackages) {
1903 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1904 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1905 while (i.hasNext()) {
1906 final PackageSetting ps = i.next();
1907 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1908 if(psPkg != null) {
1909 finalList.add(psPkg);
1910 }
1911 }
1912 }
1913 else {
1914 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1915 while (i.hasNext()) {
1916 final PackageParser.Package p = i.next();
1917 if (p.applicationInfo != null) {
1918 PackageInfo pi = generatePackageInfo(p, flags);
1919 if(pi != null) {
1920 finalList.add(pi);
1921 }
1922 }
1923 }
1924 }
1925 }
1926 return finalList;
1927 }
1928
1929 public List<ApplicationInfo> getInstalledApplications(int flags) {
1930 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1931 synchronized(mPackages) {
1932 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1933 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1934 while (i.hasNext()) {
1935 final PackageSetting ps = i.next();
1936 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1937 if(ai != null) {
1938 finalList.add(ai);
1939 }
1940 }
1941 }
1942 else {
1943 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1944 while (i.hasNext()) {
1945 final PackageParser.Package p = i.next();
1946 if (p.applicationInfo != null) {
1947 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1948 if(ai != null) {
1949 finalList.add(ai);
1950 }
1951 }
1952 }
1953 }
1954 }
1955 return finalList;
1956 }
1957
1958 public List<ApplicationInfo> getPersistentApplications(int flags) {
1959 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1960
1961 synchronized (mPackages) {
1962 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1963 while (i.hasNext()) {
1964 PackageParser.Package p = i.next();
1965 if (p.applicationInfo != null
1966 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1967 && (!mSafeMode || (p.applicationInfo.flags
1968 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1969 finalList.add(p.applicationInfo);
1970 }
1971 }
1972 }
1973
1974 return finalList;
1975 }
1976
1977 public ProviderInfo resolveContentProvider(String name, int flags) {
1978 synchronized (mPackages) {
1979 final PackageParser.Provider provider = mProviders.get(name);
1980 return provider != null
1981 && mSettings.isEnabledLP(provider.info, flags)
1982 && (!mSafeMode || (provider.info.applicationInfo.flags
1983 &ApplicationInfo.FLAG_SYSTEM) != 0)
1984 ? PackageParser.generateProviderInfo(provider, flags)
1985 : null;
1986 }
1987 }
1988
Fred Quintana718d8a22009-04-29 17:53:20 -07001989 /**
1990 * @deprecated
1991 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 public void querySyncProviders(List outNames, List outInfo) {
1993 synchronized (mPackages) {
1994 Iterator<Map.Entry<String, PackageParser.Provider>> i
1995 = mProviders.entrySet().iterator();
1996
1997 while (i.hasNext()) {
1998 Map.Entry<String, PackageParser.Provider> entry = i.next();
1999 PackageParser.Provider p = entry.getValue();
2000
2001 if (p.syncable
2002 && (!mSafeMode || (p.info.applicationInfo.flags
2003 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2004 outNames.add(entry.getKey());
2005 outInfo.add(PackageParser.generateProviderInfo(p, 0));
2006 }
2007 }
2008 }
2009 }
2010
2011 public List<ProviderInfo> queryContentProviders(String processName,
2012 int uid, int flags) {
2013 ArrayList<ProviderInfo> finalList = null;
2014
2015 synchronized (mPackages) {
2016 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2017 while (i.hasNext()) {
2018 PackageParser.Provider p = i.next();
2019 if (p.info.authority != null
2020 && (processName == null ||
2021 (p.info.processName.equals(processName)
2022 && p.info.applicationInfo.uid == uid))
2023 && mSettings.isEnabledLP(p.info, flags)
2024 && (!mSafeMode || (p.info.applicationInfo.flags
2025 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2026 if (finalList == null) {
2027 finalList = new ArrayList<ProviderInfo>(3);
2028 }
2029 finalList.add(PackageParser.generateProviderInfo(p,
2030 flags));
2031 }
2032 }
2033 }
2034
2035 if (finalList != null) {
2036 Collections.sort(finalList, mProviderInitOrderSorter);
2037 }
2038
2039 return finalList;
2040 }
2041
2042 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2043 int flags) {
2044 synchronized (mPackages) {
2045 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2046 return PackageParser.generateInstrumentationInfo(i, flags);
2047 }
2048 }
2049
2050 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2051 int flags) {
2052 ArrayList<InstrumentationInfo> finalList =
2053 new ArrayList<InstrumentationInfo>();
2054
2055 synchronized (mPackages) {
2056 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2057 while (i.hasNext()) {
2058 PackageParser.Instrumentation p = i.next();
2059 if (targetPackage == null
2060 || targetPackage.equals(p.info.targetPackage)) {
2061 finalList.add(PackageParser.generateInstrumentationInfo(p,
2062 flags));
2063 }
2064 }
2065 }
2066
2067 return finalList;
2068 }
2069
2070 private void scanDirLI(File dir, int flags, int scanMode) {
2071 Log.d(TAG, "Scanning app dir " + dir);
2072
2073 String[] files = dir.list();
2074
2075 int i;
2076 for (i=0; i<files.length; i++) {
2077 File file = new File(dir, files[i]);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002078 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
2080 }
2081 }
2082
2083 private static void reportSettingsProblem(int priority, String msg) {
2084 try {
2085 File dataDir = Environment.getDataDirectory();
2086 File systemDir = new File(dataDir, "system");
2087 File fname = new File(systemDir, "uiderrors.txt");
2088 FileOutputStream out = new FileOutputStream(fname, true);
2089 PrintWriter pw = new PrintWriter(out);
2090 pw.println(msg);
2091 pw.close();
2092 FileUtils.setPermissions(
2093 fname.toString(),
2094 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2095 -1, -1);
2096 } catch (java.io.IOException e) {
2097 }
2098 Log.println(priority, TAG, msg);
2099 }
2100
2101 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2102 PackageParser.Package pkg, File srcFile, int parseFlags) {
2103 if (GET_CERTIFICATES) {
2104 if (ps == null || !ps.codePath.equals(srcFile)
2105 || ps.getTimeStamp() != srcFile.lastModified()) {
2106 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2107 if (!pp.collectCertificates(pkg, parseFlags)) {
2108 mLastScanError = pp.getParseError();
2109 return false;
2110 }
2111 }
2112 }
2113 return true;
2114 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 /*
2117 * Scan a package and return the newly parsed package.
2118 * Returns null in case of errors and the error code is stored in mLastScanError
2119 */
2120 private PackageParser.Package scanPackageLI(File scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002121 int parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 int scanMode) {
2123 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002124 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002126 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002129 scanPath,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002130 mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 if (pkg == null) {
2132 mLastScanError = pp.getParseError();
2133 return null;
2134 }
2135 PackageSetting ps;
2136 PackageSetting updatedPkg;
2137 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002138 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2140 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002141 // Verify certificates first
2142 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2143 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2144 return null;
2145 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 if (updatedPkg != null) {
2147 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2148 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2149 }
2150 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2151 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002152 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2153 if (pkg.mVersionCode < ps.versionCode) {
2154 // The system package has been updated and the code path does not match
2155 // Ignore entry. Just return
2156 Log.w(TAG, "Package:" + pkg.packageName +
2157 " has been updated. Ignoring the one from path:"+scanFile);
2158 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2159 return null;
2160 } else {
2161 // Delete the older apk pointed to by ps
2162 // At this point, its safely assumed that package installation for
2163 // apps in system partition will go through. If not there won't be a working
2164 // version of the app
2165 synchronized (mPackages) {
2166 // Just remove the loaded entries from package lists.
2167 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002168 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002169 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2170 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002171 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173 }
2174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 // The apk is forward locked (not public) if its code and resources
2176 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002177 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002179 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002180 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002181
2182 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2183 if (ps != null && ps.resourcePathString != null) {
2184 pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
2185 } else {
2186 // Should not happen at all. Just log an error.
2187 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2188 }
2189 } else {
2190 pkg.applicationInfo.publicSourceDir = pkg.mScanPath;
2191 }
2192 pkg.applicationInfo.sourceDir = pkg.mScanPath;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002194 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 }
2196
2197 private static String fixProcessName(String defProcessName,
2198 String processName, int uid) {
2199 if (processName == null) {
2200 return defProcessName;
2201 }
2202 return processName;
2203 }
2204
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002205 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2207 if (pkg.mSignatures != null) {
2208 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2209 updateSignature)) {
2210 Log.e(TAG, "Package " + pkg.packageName
2211 + " signatures do not match the previously installed version; ignoring!");
2212 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2213 return false;
2214 }
2215
2216 if (pkgSetting.sharedUser != null) {
2217 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2218 pkg.mSignatures, updateSignature)) {
2219 Log.e(TAG, "Package " + pkg.packageName
2220 + " has no signatures that match those in shared user "
2221 + pkgSetting.sharedUser.name + "; ignoring!");
2222 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2223 return false;
2224 }
2225 }
2226 } else {
2227 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2228 }
2229 return true;
2230 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002231
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002232 public boolean performDexOpt(String packageName) {
2233 if (!mNoDexOpt) {
2234 return false;
2235 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002236
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002237 PackageParser.Package p;
2238 synchronized (mPackages) {
2239 p = mPackages.get(packageName);
2240 if (p == null || p.mDidDexOpt) {
2241 return false;
2242 }
2243 }
2244 synchronized (mInstallLock) {
2245 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2246 }
2247 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002248
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002249 static final int DEX_OPT_SKIPPED = 0;
2250 static final int DEX_OPT_PERFORMED = 1;
2251 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002252
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002253 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2254 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002255 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002256 String path = pkg.mScanPath;
2257 int ret = 0;
2258 try {
2259 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002260 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002261 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002262 pkg.mDidDexOpt = true;
2263 performed = true;
2264 }
2265 } catch (FileNotFoundException e) {
2266 Log.w(TAG, "Apk not found for dexopt: " + path);
2267 ret = -1;
2268 } catch (IOException e) {
2269 Log.w(TAG, "Exception reading apk: " + path, e);
2270 ret = -1;
2271 }
2272 if (ret < 0) {
2273 //error from installer
2274 return DEX_OPT_FAILED;
2275 }
2276 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002277
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002278 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2279 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002280
2281 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2282 return Environment.isEncryptedFilesystemEnabled() &&
2283 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2284 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 private PackageParser.Package scanPackageLI(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 PackageParser.Package pkg, int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002288 File scanFile = new File(pkg.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 mScanningPath = scanFile;
2290 if (pkg == null) {
2291 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2292 return null;
2293 }
2294
2295 final String pkgName = pkg.applicationInfo.packageName;
2296 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2297 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2298 }
2299
2300 if (pkgName.equals("android")) {
2301 synchronized (mPackages) {
2302 if (mAndroidApplication != null) {
2303 Log.w(TAG, "*************************************************");
2304 Log.w(TAG, "Core android package being redefined. Skipping.");
2305 Log.w(TAG, " file=" + mScanningPath);
2306 Log.w(TAG, "*************************************************");
2307 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2308 return null;
2309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 // Set up information for our fall-back user intent resolution
2312 // activity.
2313 mPlatformPackage = pkg;
2314 pkg.mVersionCode = mSdkVersion;
2315 mAndroidApplication = pkg.applicationInfo;
2316 mResolveActivity.applicationInfo = mAndroidApplication;
2317 mResolveActivity.name = ResolverActivity.class.getName();
2318 mResolveActivity.packageName = mAndroidApplication.packageName;
2319 mResolveActivity.processName = mAndroidApplication.processName;
2320 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2321 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2322 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2323 mResolveActivity.exported = true;
2324 mResolveActivity.enabled = true;
2325 mResolveInfo.activityInfo = mResolveActivity;
2326 mResolveInfo.priority = 0;
2327 mResolveInfo.preferredOrder = 0;
2328 mResolveInfo.match = 0;
2329 mResolveComponentName = new ComponentName(
2330 mAndroidApplication.packageName, mResolveActivity.name);
2331 }
2332 }
2333
2334 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2335 TAG, "Scanning package " + pkgName);
2336 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2337 Log.w(TAG, "*************************************************");
2338 Log.w(TAG, "Application package " + pkgName
2339 + " already installed. Skipping duplicate.");
2340 Log.w(TAG, "*************************************************");
2341 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2342 return null;
2343 }
2344
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002345 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002346 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2347 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002349 SharedUserSetting suid = null;
2350 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 synchronized (mPackages) {
2355 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002356 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2357 if (mTmpSharedLibraries == null ||
2358 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2359 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2360 }
2361 int num = 0;
2362 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2363 for (int i=0; i<N; i++) {
2364 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 if (file == null) {
2366 Log.e(TAG, "Package " + pkg.packageName
2367 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002368 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2370 return null;
2371 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002372 mTmpSharedLibraries[num] = file;
2373 num++;
2374 }
2375 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2376 for (int i=0; i<N; i++) {
2377 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2378 if (file == null) {
2379 Log.w(TAG, "Package " + pkg.packageName
2380 + " desires unavailable shared library "
2381 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2382 } else {
2383 mTmpSharedLibraries[num] = file;
2384 num++;
2385 }
2386 }
2387 if (num > 0) {
2388 pkg.usesLibraryFiles = new String[num];
2389 System.arraycopy(mTmpSharedLibraries, 0,
2390 pkg.usesLibraryFiles, 0, num);
2391 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002392
Dianne Hackborn49237342009-08-27 20:08:01 -07002393 if (pkg.reqFeatures != null) {
2394 N = pkg.reqFeatures.size();
2395 for (int i=0; i<N; i++) {
2396 FeatureInfo fi = pkg.reqFeatures.get(i);
2397 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2398 // Don't care.
2399 continue;
2400 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002401
Dianne Hackborn49237342009-08-27 20:08:01 -07002402 if (fi.name != null) {
2403 if (mAvailableFeatures.get(fi.name) == null) {
2404 Log.e(TAG, "Package " + pkg.packageName
2405 + " requires unavailable feature "
2406 + fi.name + "; failing!");
2407 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2408 return null;
2409 }
2410 }
2411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 }
2413 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 if (pkg.mSharedUserId != null) {
2416 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2417 pkg.applicationInfo.flags, true);
2418 if (suid == null) {
2419 Log.w(TAG, "Creating application package " + pkgName
2420 + " for shared user failed");
2421 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2422 return null;
2423 }
2424 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2425 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2426 + suid.userId + "): packages=" + suid.packages);
2427 }
2428 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002429
2430 // Just create the setting, don't add it yet. For already existing packages
2431 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002432 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2433 destResourceFile, pkg.applicationInfo.flags, true, false);
2434 if (pkgSetting == null) {
2435 Log.w(TAG, "Creating application package " + pkgName + " failed");
2436 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2437 return null;
2438 }
2439 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2440 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2441 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002443 pkg.applicationInfo.uid = pkgSetting.userId;
2444 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002445
2446 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2448 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2449 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2450 return null;
2451 }
2452 // The signature has changed, but this package is in the system
2453 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002454 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 // However... if this package is part of a shared user, but it
2456 // doesn't match the signature of the shared user, let's fail.
2457 // What this means is that you can't change the signatures
2458 // associated with an overall shared user, which doesn't seem all
2459 // that unreasonable.
2460 if (pkgSetting.sharedUser != null) {
2461 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2462 pkg.mSignatures, false)) {
2463 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2464 return null;
2465 }
2466 }
2467 removeExisting = true;
2468 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002469
The Android Open Source Project10592532009-03-18 17:39:46 -07002470 // Verify that this new package doesn't have any content providers
2471 // that conflict with existing packages. Only do this if the
2472 // package isn't already installed, since we don't want to break
2473 // things that are installed.
2474 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2475 int N = pkg.providers.size();
2476 int i;
2477 for (i=0; i<N; i++) {
2478 PackageParser.Provider p = pkg.providers.get(i);
2479 String names[] = p.info.authority.split(";");
2480 for (int j = 0; j < names.length; j++) {
2481 if (mProviders.containsKey(names[j])) {
2482 PackageParser.Provider other = mProviders.get(names[j]);
2483 Log.w(TAG, "Can't install because provider name " + names[j] +
2484 " (in package " + pkg.applicationInfo.packageName +
2485 ") is already used by "
2486 + ((other != null && other.component != null)
2487 ? other.component.getPackageName() : "?"));
2488 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2489 return null;
2490 }
2491 }
2492 }
2493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 }
2495
2496 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002497 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002499 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 if (ret != 0) {
2501 String msg = "System package " + pkg.packageName
2502 + " could not have data directory erased after signature change.";
2503 reportSettingsProblem(Log.WARN, msg);
2504 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2505 return null;
2506 }
2507 }
2508 Log.w(TAG, "System package " + pkg.packageName
2509 + " signature changed: existing data removed.");
2510 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2511 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513 long scanFileTime = scanFile.lastModified();
2514 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2515 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2516 pkg.applicationInfo.processName = fixProcessName(
2517 pkg.applicationInfo.packageName,
2518 pkg.applicationInfo.processName,
2519 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520
2521 File dataPath;
2522 if (mPlatformPackage == pkg) {
2523 // The system package is special.
2524 dataPath = new File (Environment.getDataDirectory(), "system");
2525 pkg.applicationInfo.dataDir = dataPath.getPath();
2526 } else {
2527 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002528 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2529 if (useEncryptedFSDir) {
2530 dataPath = new File(mSecureAppDataDir, pkgName);
2531 } else {
2532 dataPath = new File(mAppDataDir, pkgName);
2533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 if (dataPath.exists()) {
2535 mOutPermissions[1] = 0;
2536 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2537 if (mOutPermissions[1] == pkg.applicationInfo.uid
2538 || !Process.supportsProcesses()) {
2539 pkg.applicationInfo.dataDir = dataPath.getPath();
2540 } else {
2541 boolean recovered = false;
2542 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2543 // If this is a system app, we can at least delete its
2544 // current data so the application will still work.
2545 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002546 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002547 if(ret >= 0) {
2548 // Old data gone!
2549 String msg = "System package " + pkg.packageName
2550 + " has changed from uid: "
2551 + mOutPermissions[1] + " to "
2552 + pkg.applicationInfo.uid + "; old data erased";
2553 reportSettingsProblem(Log.WARN, msg);
2554 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002557 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 pkg.applicationInfo.uid);
2559 if (ret == -1) {
2560 // Ack should not happen!
2561 msg = "System package " + pkg.packageName
2562 + " could not have data directory re-created after delete.";
2563 reportSettingsProblem(Log.WARN, msg);
2564 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2565 return null;
2566 }
2567 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002569 if (!recovered) {
2570 mHasSystemUidErrors = true;
2571 }
2572 }
2573 if (!recovered) {
2574 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2575 + pkg.applicationInfo.uid + "/fs_"
2576 + mOutPermissions[1];
2577 String msg = "Package " + pkg.packageName
2578 + " has mismatched uid: "
2579 + mOutPermissions[1] + " on disk, "
2580 + pkg.applicationInfo.uid + " in settings";
2581 synchronized (mPackages) {
2582 if (!mReportedUidError) {
2583 mReportedUidError = true;
2584 msg = msg + "; read messages:\n"
2585 + mSettings.getReadMessagesLP();
2586 }
2587 reportSettingsProblem(Log.ERROR, msg);
2588 }
2589 }
2590 }
2591 pkg.applicationInfo.dataDir = dataPath.getPath();
2592 } else {
2593 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2594 Log.v(TAG, "Want this data dir: " + dataPath);
2595 //invoke installer to do the actual installation
2596 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002597 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 pkg.applicationInfo.uid);
2599 if(ret < 0) {
2600 // Error from installer
2601 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2602 return null;
2603 }
2604 } else {
2605 dataPath.mkdirs();
2606 if (dataPath.exists()) {
2607 FileUtils.setPermissions(
2608 dataPath.toString(),
2609 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2610 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2611 }
2612 }
2613 if (dataPath.exists()) {
2614 pkg.applicationInfo.dataDir = dataPath.getPath();
2615 } else {
2616 Log.w(TAG, "Unable to create data directory: " + dataPath);
2617 pkg.applicationInfo.dataDir = null;
2618 }
2619 }
2620 }
2621
2622 // Perform shared library installation and dex validation and
2623 // optimization, if this is not a system app.
2624 if (mInstaller != null) {
2625 String path = scanFile.getPath();
2626 if (scanFileNewer) {
2627 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002628 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2629 if (err != PackageManager.INSTALL_SUCCEEDED) {
2630 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 return null;
2632 }
2633 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002634 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002635
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002636 if ((scanMode&SCAN_NO_DEX) == 0) {
2637 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2639 return null;
2640 }
2641 }
2642 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 if (mFactoryTest && pkg.requestedPermissions.contains(
2645 android.Manifest.permission.FACTORY_TEST)) {
2646 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2647 }
2648
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002649 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 if ((scanMode&SCAN_MONITOR) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002651 mAppDirs.put(pkg.mPath, pkg);
2652 }
2653
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002654 // Request the ActivityManager to kill the process(only for existing packages)
2655 // so that we do not end up in a confused state while the user is still using the older
2656 // version of the application while the new one gets installed.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002657 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0) {
2658 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002659 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002660 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002663 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002664 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002666 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 int N = pkg.providers.size();
2668 StringBuilder r = null;
2669 int i;
2670 for (i=0; i<N; i++) {
2671 PackageParser.Provider p = pkg.providers.get(i);
2672 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2673 p.info.processName, pkg.applicationInfo.uid);
2674 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2675 p.info.name), p);
2676 p.syncable = p.info.isSyncable;
2677 String names[] = p.info.authority.split(";");
2678 p.info.authority = null;
2679 for (int j = 0; j < names.length; j++) {
2680 if (j == 1 && p.syncable) {
2681 // We only want the first authority for a provider to possibly be
2682 // syncable, so if we already added this provider using a different
2683 // authority clear the syncable flag. We copy the provider before
2684 // changing it because the mProviders object contains a reference
2685 // to a provider that we don't want to change.
2686 // Only do this for the second authority since the resulting provider
2687 // object can be the same for all future authorities for this provider.
2688 p = new PackageParser.Provider(p);
2689 p.syncable = false;
2690 }
2691 if (!mProviders.containsKey(names[j])) {
2692 mProviders.put(names[j], p);
2693 if (p.info.authority == null) {
2694 p.info.authority = names[j];
2695 } else {
2696 p.info.authority = p.info.authority + ";" + names[j];
2697 }
2698 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2699 Log.d(TAG, "Registered content provider: " + names[j] +
2700 ", className = " + p.info.name +
2701 ", isSyncable = " + p.info.isSyncable);
2702 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002703 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 Log.w(TAG, "Skipping provider name " + names[j] +
2705 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002706 "): name already used by "
2707 + ((other != null && other.component != null)
2708 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002709 }
2710 }
2711 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2712 if (r == null) {
2713 r = new StringBuilder(256);
2714 } else {
2715 r.append(' ');
2716 }
2717 r.append(p.info.name);
2718 }
2719 }
2720 if (r != null) {
2721 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2722 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002724 N = pkg.services.size();
2725 r = null;
2726 for (i=0; i<N; i++) {
2727 PackageParser.Service s = pkg.services.get(i);
2728 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2729 s.info.processName, pkg.applicationInfo.uid);
2730 mServices.addService(s);
2731 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2732 if (r == null) {
2733 r = new StringBuilder(256);
2734 } else {
2735 r.append(' ');
2736 }
2737 r.append(s.info.name);
2738 }
2739 }
2740 if (r != null) {
2741 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2742 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744 N = pkg.receivers.size();
2745 r = null;
2746 for (i=0; i<N; i++) {
2747 PackageParser.Activity a = pkg.receivers.get(i);
2748 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2749 a.info.processName, pkg.applicationInfo.uid);
2750 mReceivers.addActivity(a, "receiver");
2751 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2752 if (r == null) {
2753 r = new StringBuilder(256);
2754 } else {
2755 r.append(' ');
2756 }
2757 r.append(a.info.name);
2758 }
2759 }
2760 if (r != null) {
2761 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2762 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002764 N = pkg.activities.size();
2765 r = null;
2766 for (i=0; i<N; i++) {
2767 PackageParser.Activity a = pkg.activities.get(i);
2768 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2769 a.info.processName, pkg.applicationInfo.uid);
2770 mActivities.addActivity(a, "activity");
2771 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2772 if (r == null) {
2773 r = new StringBuilder(256);
2774 } else {
2775 r.append(' ');
2776 }
2777 r.append(a.info.name);
2778 }
2779 }
2780 if (r != null) {
2781 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2782 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002784 N = pkg.permissionGroups.size();
2785 r = null;
2786 for (i=0; i<N; i++) {
2787 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2788 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2789 if (cur == null) {
2790 mPermissionGroups.put(pg.info.name, pg);
2791 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2792 if (r == null) {
2793 r = new StringBuilder(256);
2794 } else {
2795 r.append(' ');
2796 }
2797 r.append(pg.info.name);
2798 }
2799 } else {
2800 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2801 + pg.info.packageName + " ignored: original from "
2802 + cur.info.packageName);
2803 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2804 if (r == null) {
2805 r = new StringBuilder(256);
2806 } else {
2807 r.append(' ');
2808 }
2809 r.append("DUP:");
2810 r.append(pg.info.name);
2811 }
2812 }
2813 }
2814 if (r != null) {
2815 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2816 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 N = pkg.permissions.size();
2819 r = null;
2820 for (i=0; i<N; i++) {
2821 PackageParser.Permission p = pkg.permissions.get(i);
2822 HashMap<String, BasePermission> permissionMap =
2823 p.tree ? mSettings.mPermissionTrees
2824 : mSettings.mPermissions;
2825 p.group = mPermissionGroups.get(p.info.group);
2826 if (p.info.group == null || p.group != null) {
2827 BasePermission bp = permissionMap.get(p.info.name);
2828 if (bp == null) {
2829 bp = new BasePermission(p.info.name, p.info.packageName,
2830 BasePermission.TYPE_NORMAL);
2831 permissionMap.put(p.info.name, bp);
2832 }
2833 if (bp.perm == null) {
2834 if (bp.sourcePackage == null
2835 || bp.sourcePackage.equals(p.info.packageName)) {
2836 BasePermission tree = findPermissionTreeLP(p.info.name);
2837 if (tree == null
2838 || tree.sourcePackage.equals(p.info.packageName)) {
2839 bp.perm = p;
2840 bp.uid = pkg.applicationInfo.uid;
2841 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2842 if (r == null) {
2843 r = new StringBuilder(256);
2844 } else {
2845 r.append(' ');
2846 }
2847 r.append(p.info.name);
2848 }
2849 } else {
2850 Log.w(TAG, "Permission " + p.info.name + " from package "
2851 + p.info.packageName + " ignored: base tree "
2852 + tree.name + " is from package "
2853 + tree.sourcePackage);
2854 }
2855 } else {
2856 Log.w(TAG, "Permission " + p.info.name + " from package "
2857 + p.info.packageName + " ignored: original from "
2858 + bp.sourcePackage);
2859 }
2860 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2861 if (r == null) {
2862 r = new StringBuilder(256);
2863 } else {
2864 r.append(' ');
2865 }
2866 r.append("DUP:");
2867 r.append(p.info.name);
2868 }
2869 } else {
2870 Log.w(TAG, "Permission " + p.info.name + " from package "
2871 + p.info.packageName + " ignored: no group "
2872 + p.group);
2873 }
2874 }
2875 if (r != null) {
2876 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2877 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002879 N = pkg.instrumentation.size();
2880 r = null;
2881 for (i=0; i<N; i++) {
2882 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2883 a.info.packageName = pkg.applicationInfo.packageName;
2884 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2885 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2886 a.info.dataDir = pkg.applicationInfo.dataDir;
2887 mInstrumentation.put(a.component, a);
2888 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2889 if (r == null) {
2890 r = new StringBuilder(256);
2891 } else {
2892 r.append(' ');
2893 }
2894 r.append(a.info.name);
2895 }
2896 }
2897 if (r != null) {
2898 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2899 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002900
Dianne Hackborn854060af2009-07-09 18:14:31 -07002901 if (pkg.protectedBroadcasts != null) {
2902 N = pkg.protectedBroadcasts.size();
2903 for (i=0; i<N; i++) {
2904 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2905 }
2906 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 pkgSetting.setTimeStamp(scanFileTime);
2909 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 return pkg;
2912 }
2913
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002914 private void killApplication(String pkgName, int uid) {
2915 // Request the ActivityManager to kill the process(only for existing packages)
2916 // so that we do not end up in a confused state while the user is still using the older
2917 // version of the application while the new one gets installed.
2918 IActivityManager am = ActivityManagerNative.getDefault();
2919 if (am != null) {
2920 try {
2921 am.killApplicationWithUid(pkgName, uid);
2922 } catch (RemoteException e) {
2923 }
2924 }
2925 }
2926
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002927 // The following constants are returned by cachePackageSharedLibsForAbiLI
2928 // to indicate if native shared libraries were found in the package.
2929 // Values are:
2930 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2931 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2932 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2933 // in package (and not installed)
2934 //
2935 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2936 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2937 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002939 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2940 // and automatically copy them to /data/data/<appname>/lib if present.
2941 //
2942 // NOTE: this method may throw an IOException if the library cannot
2943 // be copied to its final destination, e.g. if there isn't enough
2944 // room left on the data partition, or a ZipException if the package
2945 // file is malformed.
2946 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08002947 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
2948 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002949 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2950 final String apkLib = "lib/";
2951 final int apkLibLen = apkLib.length();
2952 final int cpuAbiLen = cpuAbi.length();
2953 final String libPrefix = "lib";
2954 final int libPrefixLen = libPrefix.length();
2955 final String libSuffix = ".so";
2956 final int libSuffixLen = libSuffix.length();
2957 boolean hasNativeLibraries = false;
2958 boolean installedNativeLibraries = false;
2959
2960 // the minimum length of a valid native shared library of the form
2961 // lib/<something>/lib<name>.so.
2962 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2963
2964 ZipFile zipFile = new ZipFile(scanFile);
2965 Enumeration<ZipEntry> entries =
2966 (Enumeration<ZipEntry>) zipFile.entries();
2967
2968 while (entries.hasMoreElements()) {
2969 ZipEntry entry = entries.nextElement();
2970 // skip directories
2971 if (entry.isDirectory()) {
2972 continue;
2973 }
2974 String entryName = entry.getName();
2975
2976 // check that the entry looks like lib/<something>/lib<name>.so
2977 // here, but don't check the ABI just yet.
2978 //
2979 // - must be sufficiently long
2980 // - must end with libSuffix, i.e. ".so"
2981 // - must start with apkLib, i.e. "lib/"
2982 if (entryName.length() < minEntryLen ||
2983 !entryName.endsWith(libSuffix) ||
2984 !entryName.startsWith(apkLib) ) {
2985 continue;
2986 }
2987
2988 // file name must start with libPrefix, i.e. "lib"
2989 int lastSlash = entryName.lastIndexOf('/');
2990
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002991 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002992 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2993 continue;
2994 }
2995
2996 hasNativeLibraries = true;
2997
2998 // check the cpuAbi now, between lib/ and /lib<name>.so
2999 //
3000 if (lastSlash != apkLibLen + cpuAbiLen ||
3001 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
3002 continue;
3003
3004 // extract the library file name, ensure it doesn't contain
3005 // weird characters. we're guaranteed here that it doesn't contain
3006 // a directory separator though.
3007 String libFileName = entryName.substring(lastSlash+1);
3008 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
3009 continue;
3010 }
3011
3012 installedNativeLibraries = true;
3013
3014 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3015 File.separator + libFileName;
3016 File sharedLibraryFile = new File(sharedLibraryFilePath);
3017 if (! sharedLibraryFile.exists() ||
3018 sharedLibraryFile.length() != entry.getSize() ||
3019 sharedLibraryFile.lastModified() != entry.getTime()) {
3020 if (Config.LOGD) {
3021 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003022 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003023 if (mInstaller == null) {
3024 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003025 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003026 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003027 sharedLibraryFile);
3028 }
3029 }
3030 if (!hasNativeLibraries)
3031 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3032
3033 if (!installedNativeLibraries)
3034 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3035
3036 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3037 }
3038
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003039 // Find the gdbserver executable program in a package at
3040 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3041 //
3042 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3043 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3044 //
3045 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3046 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3047 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3048 final String GDBSERVER = "gdbserver";
3049 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3050
3051 ZipFile zipFile = new ZipFile(scanFile);
3052 Enumeration<ZipEntry> entries =
3053 (Enumeration<ZipEntry>) zipFile.entries();
3054
3055 while (entries.hasMoreElements()) {
3056 ZipEntry entry = entries.nextElement();
3057 // skip directories
3058 if (entry.isDirectory()) {
3059 continue;
3060 }
3061 String entryName = entry.getName();
3062
3063 if (!entryName.equals(apkGdbServerPath)) {
3064 continue;
3065 }
3066
3067 String installGdbServerPath = installGdbServerDir.getPath() +
3068 "/" + GDBSERVER;
3069 File installGdbServerFile = new File(installGdbServerPath);
3070 if (! installGdbServerFile.exists() ||
3071 installGdbServerFile.length() != entry.getSize() ||
3072 installGdbServerFile.lastModified() != entry.getTime()) {
3073 if (Config.LOGD) {
3074 Log.d(TAG, "Caching gdbserver " + entry.getName());
3075 }
3076 if (mInstaller == null) {
3077 installGdbServerDir.mkdir();
3078 }
3079 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3080 installGdbServerFile);
3081 }
3082 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3083 }
3084 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3085 }
3086
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003087 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3088 // and copy them to /data/data/<appname>/lib.
3089 //
3090 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3091 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3092 // one if ro.product.cpu.abi2 is defined.
3093 //
3094 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3095 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003096 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003097 try {
3098 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3099
3100 // some architectures are capable of supporting several CPU ABIs
3101 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3102 // this is indicated by the definition of the ro.product.cpu.abi2
3103 // system property.
3104 //
3105 // only scan the package twice in case of ABI mismatch
3106 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003107 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003108 if (cpuAbi2 != null) {
3109 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003111
3112 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3113 Log.w(TAG,"Native ABI mismatch from package file");
3114 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003116
3117 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3118 cpuAbi = cpuAbi2;
3119 }
3120 }
3121
3122 // for debuggable packages, also extract gdbserver from lib/<abi>
3123 // into /data/data/<appname>/lib too.
3124 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3125 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3126 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3127 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3128 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003130 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003131 } catch (ZipException e) {
3132 Log.w(TAG, "Failed to extract data from package file", e);
3133 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003135 Log.w(TAG, "Failed to cache package shared libs", e);
3136 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003138 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003139 }
3140
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003141 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003142 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003143 File binaryDir,
3144 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 InputStream inputStream = zipFile.getInputStream(entry);
3146 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003147 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003149 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 // now need to be left as world readable and owned by the system.
3151 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3152 ! tempFile.setLastModified(entry.getTime()) ||
3153 FileUtils.setPermissions(tempFilePath,
3154 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003155 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003156 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003157 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003158 // Failed to properly write file.
3159 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003160 throw new IOException("Couldn't create cached binary "
3161 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 }
3163 } finally {
3164 inputStream.close();
3165 }
3166 }
3167
3168 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3169 if (chatty && Config.LOGD) Log.d(
3170 TAG, "Removing package " + pkg.applicationInfo.packageName );
3171
3172 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 mPackages.remove(pkg.applicationInfo.packageName);
3176 if (pkg.mPath != null) {
3177 mAppDirs.remove(pkg.mPath);
3178 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 PackageSetting ps = (PackageSetting)pkg.mExtras;
3181 if (ps != null && ps.sharedUser != null) {
3182 // XXX don't do this until the data is removed.
3183 if (false) {
3184 ps.sharedUser.packages.remove(ps);
3185 if (ps.sharedUser.packages.size() == 0) {
3186 // Remove.
3187 }
3188 }
3189 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 int N = pkg.providers.size();
3192 StringBuilder r = null;
3193 int i;
3194 for (i=0; i<N; i++) {
3195 PackageParser.Provider p = pkg.providers.get(i);
3196 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3197 p.info.name));
3198 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 /* The is another ContentProvider with this authority when
3201 * this app was installed so this authority is null,
3202 * Ignore it as we don't have to unregister the provider.
3203 */
3204 continue;
3205 }
3206 String names[] = p.info.authority.split(";");
3207 for (int j = 0; j < names.length; j++) {
3208 if (mProviders.get(names[j]) == p) {
3209 mProviders.remove(names[j]);
3210 if (chatty && Config.LOGD) Log.d(
3211 TAG, "Unregistered content provider: " + names[j] +
3212 ", className = " + p.info.name +
3213 ", isSyncable = " + p.info.isSyncable);
3214 }
3215 }
3216 if (chatty) {
3217 if (r == null) {
3218 r = new StringBuilder(256);
3219 } else {
3220 r.append(' ');
3221 }
3222 r.append(p.info.name);
3223 }
3224 }
3225 if (r != null) {
3226 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3227 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003229 N = pkg.services.size();
3230 r = null;
3231 for (i=0; i<N; i++) {
3232 PackageParser.Service s = pkg.services.get(i);
3233 mServices.removeService(s);
3234 if (chatty) {
3235 if (r == null) {
3236 r = new StringBuilder(256);
3237 } else {
3238 r.append(' ');
3239 }
3240 r.append(s.info.name);
3241 }
3242 }
3243 if (r != null) {
3244 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3245 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 N = pkg.receivers.size();
3248 r = null;
3249 for (i=0; i<N; i++) {
3250 PackageParser.Activity a = pkg.receivers.get(i);
3251 mReceivers.removeActivity(a, "receiver");
3252 if (chatty) {
3253 if (r == null) {
3254 r = new StringBuilder(256);
3255 } else {
3256 r.append(' ');
3257 }
3258 r.append(a.info.name);
3259 }
3260 }
3261 if (r != null) {
3262 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3263 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003265 N = pkg.activities.size();
3266 r = null;
3267 for (i=0; i<N; i++) {
3268 PackageParser.Activity a = pkg.activities.get(i);
3269 mActivities.removeActivity(a, "activity");
3270 if (chatty) {
3271 if (r == null) {
3272 r = new StringBuilder(256);
3273 } else {
3274 r.append(' ');
3275 }
3276 r.append(a.info.name);
3277 }
3278 }
3279 if (r != null) {
3280 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3281 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 N = pkg.permissions.size();
3284 r = null;
3285 for (i=0; i<N; i++) {
3286 PackageParser.Permission p = pkg.permissions.get(i);
3287 boolean tree = false;
3288 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3289 if (bp == null) {
3290 tree = true;
3291 bp = mSettings.mPermissionTrees.get(p.info.name);
3292 }
3293 if (bp != null && bp.perm == p) {
3294 if (bp.type != BasePermission.TYPE_BUILTIN) {
3295 if (tree) {
3296 mSettings.mPermissionTrees.remove(p.info.name);
3297 } else {
3298 mSettings.mPermissions.remove(p.info.name);
3299 }
3300 } else {
3301 bp.perm = null;
3302 }
3303 if (chatty) {
3304 if (r == null) {
3305 r = new StringBuilder(256);
3306 } else {
3307 r.append(' ');
3308 }
3309 r.append(p.info.name);
3310 }
3311 }
3312 }
3313 if (r != null) {
3314 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3315 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003317 N = pkg.instrumentation.size();
3318 r = null;
3319 for (i=0; i<N; i++) {
3320 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3321 mInstrumentation.remove(a.component);
3322 if (chatty) {
3323 if (r == null) {
3324 r = new StringBuilder(256);
3325 } else {
3326 r.append(' ');
3327 }
3328 r.append(a.info.name);
3329 }
3330 }
3331 if (r != null) {
3332 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3333 }
3334 }
3335 }
3336
3337 private static final boolean isPackageFilename(String name) {
3338 return name != null && name.endsWith(".apk");
3339 }
3340
3341 private void updatePermissionsLP() {
3342 // Make sure there are no dangling permission trees.
3343 Iterator<BasePermission> it = mSettings.mPermissionTrees
3344 .values().iterator();
3345 while (it.hasNext()) {
3346 BasePermission bp = it.next();
3347 if (bp.perm == null) {
3348 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3349 + " from package " + bp.sourcePackage);
3350 it.remove();
3351 }
3352 }
3353
3354 // Make sure all dynamic permissions have been assigned to a package,
3355 // and make sure there are no dangling permissions.
3356 it = mSettings.mPermissions.values().iterator();
3357 while (it.hasNext()) {
3358 BasePermission bp = it.next();
3359 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3360 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3361 + bp.name + " pkg=" + bp.sourcePackage
3362 + " info=" + bp.pendingInfo);
3363 if (bp.perm == null && bp.pendingInfo != null) {
3364 BasePermission tree = findPermissionTreeLP(bp.name);
3365 if (tree != null) {
3366 bp.perm = new PackageParser.Permission(tree.perm.owner,
3367 new PermissionInfo(bp.pendingInfo));
3368 bp.perm.info.packageName = tree.perm.info.packageName;
3369 bp.perm.info.name = bp.name;
3370 bp.uid = tree.uid;
3371 }
3372 }
3373 }
3374 if (bp.perm == null) {
3375 Log.w(TAG, "Removing dangling permission: " + bp.name
3376 + " from package " + bp.sourcePackage);
3377 it.remove();
3378 }
3379 }
3380
3381 // Now update the permissions for all packages, in particular
3382 // replace the granted permissions of the system packages.
3383 for (PackageParser.Package pkg : mPackages.values()) {
3384 grantPermissionsLP(pkg, false);
3385 }
3386 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3389 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3390 if (ps == null) {
3391 return;
3392 }
3393 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3394 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003396 if (replace) {
3397 ps.permissionsFixed = false;
3398 if (gp == ps) {
3399 gp.grantedPermissions.clear();
3400 gp.gids = mGlobalGids;
3401 }
3402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 if (gp.gids == null) {
3405 gp.gids = mGlobalGids;
3406 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003408 final int N = pkg.requestedPermissions.size();
3409 for (int i=0; i<N; i++) {
3410 String name = pkg.requestedPermissions.get(i);
3411 BasePermission bp = mSettings.mPermissions.get(name);
3412 PackageParser.Permission p = bp != null ? bp.perm : null;
3413 if (false) {
3414 if (gp != ps) {
3415 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3416 + ": " + p);
3417 }
3418 }
3419 if (p != null) {
3420 final String perm = p.info.name;
3421 boolean allowed;
3422 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3423 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3424 allowed = true;
3425 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3426 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003427 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003429 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430 == PackageManager.SIGNATURE_MATCH);
3431 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3432 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3433 // For updated system applications, the signatureOrSystem permission
3434 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003435 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3437 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3438 if(sysPs.grantedPermissions.contains(perm)) {
3439 allowed = true;
3440 } else {
3441 allowed = false;
3442 }
3443 } else {
3444 allowed = true;
3445 }
3446 }
3447 }
3448 } else {
3449 allowed = false;
3450 }
3451 if (false) {
3452 if (gp != ps) {
3453 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3454 }
3455 }
3456 if (allowed) {
3457 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3458 && ps.permissionsFixed) {
3459 // If this is an existing, non-system package, then
3460 // we can't add any new permissions to it.
3461 if (!gp.loadedPermissions.contains(perm)) {
3462 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003463 // Except... if this is a permission that was added
3464 // to the platform (note: need to only do this when
3465 // updating the platform).
3466 final int NP = PackageParser.NEW_PERMISSIONS.length;
3467 for (int ip=0; ip<NP; ip++) {
3468 final PackageParser.NewPermissionInfo npi
3469 = PackageParser.NEW_PERMISSIONS[ip];
3470 if (npi.name.equals(perm)
3471 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3472 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003473 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003474 + pkg.packageName);
3475 break;
3476 }
3477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 }
3479 }
3480 if (allowed) {
3481 if (!gp.grantedPermissions.contains(perm)) {
3482 addedPermission = true;
3483 gp.grantedPermissions.add(perm);
3484 gp.gids = appendInts(gp.gids, bp.gids);
3485 }
3486 } else {
3487 Log.w(TAG, "Not granting permission " + perm
3488 + " to package " + pkg.packageName
3489 + " because it was previously installed without");
3490 }
3491 } else {
3492 Log.w(TAG, "Not granting permission " + perm
3493 + " to package " + pkg.packageName
3494 + " (protectionLevel=" + p.info.protectionLevel
3495 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3496 + ")");
3497 }
3498 } else {
3499 Log.w(TAG, "Unknown permission " + name
3500 + " in package " + pkg.packageName);
3501 }
3502 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003504 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003505 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3506 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 // This is the first that we have heard about this package, so the
3508 // permissions we have now selected are fixed until explicitly
3509 // changed.
3510 ps.permissionsFixed = true;
3511 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3512 }
3513 }
3514
3515 private final class ActivityIntentResolver
3516 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003517 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003519 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 }
3521
Mihai Preda074edef2009-05-18 17:13:31 +02003522 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003524 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3526 }
3527
Mihai Predaeae850c2009-05-13 10:13:48 +02003528 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3529 ArrayList<PackageParser.Activity> packageActivities) {
3530 if (packageActivities == null) {
3531 return null;
3532 }
3533 mFlags = flags;
3534 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3535 int N = packageActivities.size();
3536 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3537 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003538
3539 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003540 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003541 intentFilters = packageActivities.get(i).intents;
3542 if (intentFilters != null && intentFilters.size() > 0) {
3543 listCut.add(intentFilters);
3544 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003545 }
3546 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3547 }
3548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 public final void addActivity(PackageParser.Activity a, String type) {
3550 mActivities.put(a.component, a);
3551 if (SHOW_INFO || Config.LOGV) Log.v(
3552 TAG, " " + type + " " +
3553 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3554 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3555 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003556 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3558 if (SHOW_INFO || Config.LOGV) {
3559 Log.v(TAG, " IntentFilter:");
3560 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3561 }
3562 if (!intent.debugCheck()) {
3563 Log.w(TAG, "==> For Activity " + a.info.name);
3564 }
3565 addFilter(intent);
3566 }
3567 }
3568
3569 public final void removeActivity(PackageParser.Activity a, String type) {
3570 mActivities.remove(a.component);
3571 if (SHOW_INFO || Config.LOGV) Log.v(
3572 TAG, " " + type + " " +
3573 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3574 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3575 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003576 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3578 if (SHOW_INFO || Config.LOGV) {
3579 Log.v(TAG, " IntentFilter:");
3580 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3581 }
3582 removeFilter(intent);
3583 }
3584 }
3585
3586 @Override
3587 protected boolean allowFilterResult(
3588 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3589 ActivityInfo filterAi = filter.activity.info;
3590 for (int i=dest.size()-1; i>=0; i--) {
3591 ActivityInfo destAi = dest.get(i).activityInfo;
3592 if (destAi.name == filterAi.name
3593 && destAi.packageName == filterAi.packageName) {
3594 return false;
3595 }
3596 }
3597 return true;
3598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 @Override
3601 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3602 int match) {
3603 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3604 return null;
3605 }
3606 final PackageParser.Activity activity = info.activity;
3607 if (mSafeMode && (activity.info.applicationInfo.flags
3608 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3609 return null;
3610 }
3611 final ResolveInfo res = new ResolveInfo();
3612 res.activityInfo = PackageParser.generateActivityInfo(activity,
3613 mFlags);
3614 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3615 res.filter = info;
3616 }
3617 res.priority = info.getPriority();
3618 res.preferredOrder = activity.owner.mPreferredOrder;
3619 //System.out.println("Result: " + res.activityInfo.className +
3620 // " = " + res.priority);
3621 res.match = match;
3622 res.isDefault = info.hasDefault;
3623 res.labelRes = info.labelRes;
3624 res.nonLocalizedLabel = info.nonLocalizedLabel;
3625 res.icon = info.icon;
3626 return res;
3627 }
3628
3629 @Override
3630 protected void sortResults(List<ResolveInfo> results) {
3631 Collections.sort(results, mResolvePrioritySorter);
3632 }
3633
3634 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003635 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003637 out.print(prefix); out.print(
3638 Integer.toHexString(System.identityHashCode(filter.activity)));
3639 out.print(' ');
3640 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003641 }
3642
3643// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3644// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3645// final List<ResolveInfo> retList = Lists.newArrayList();
3646// while (i.hasNext()) {
3647// final ResolveInfo resolveInfo = i.next();
3648// if (isEnabledLP(resolveInfo.activityInfo)) {
3649// retList.add(resolveInfo);
3650// }
3651// }
3652// return retList;
3653// }
3654
3655 // Keys are String (activity class name), values are Activity.
3656 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3657 = new HashMap<ComponentName, PackageParser.Activity>();
3658 private int mFlags;
3659 }
3660
3661 private final class ServiceIntentResolver
3662 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003663 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003665 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003666 }
3667
Mihai Preda074edef2009-05-18 17:13:31 +02003668 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003669 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003670 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3672 }
3673
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003674 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3675 ArrayList<PackageParser.Service> packageServices) {
3676 if (packageServices == null) {
3677 return null;
3678 }
3679 mFlags = flags;
3680 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3681 int N = packageServices.size();
3682 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3683 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3684
3685 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3686 for (int i = 0; i < N; ++i) {
3687 intentFilters = packageServices.get(i).intents;
3688 if (intentFilters != null && intentFilters.size() > 0) {
3689 listCut.add(intentFilters);
3690 }
3691 }
3692 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3693 }
3694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003695 public final void addService(PackageParser.Service s) {
3696 mServices.put(s.component, s);
3697 if (SHOW_INFO || Config.LOGV) Log.v(
3698 TAG, " " + (s.info.nonLocalizedLabel != null
3699 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3700 if (SHOW_INFO || Config.LOGV) Log.v(
3701 TAG, " Class=" + s.info.name);
3702 int NI = s.intents.size();
3703 int j;
3704 for (j=0; j<NI; j++) {
3705 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3706 if (SHOW_INFO || Config.LOGV) {
3707 Log.v(TAG, " IntentFilter:");
3708 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3709 }
3710 if (!intent.debugCheck()) {
3711 Log.w(TAG, "==> For Service " + s.info.name);
3712 }
3713 addFilter(intent);
3714 }
3715 }
3716
3717 public final void removeService(PackageParser.Service s) {
3718 mServices.remove(s.component);
3719 if (SHOW_INFO || Config.LOGV) Log.v(
3720 TAG, " " + (s.info.nonLocalizedLabel != null
3721 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3722 if (SHOW_INFO || Config.LOGV) Log.v(
3723 TAG, " Class=" + s.info.name);
3724 int NI = s.intents.size();
3725 int j;
3726 for (j=0; j<NI; j++) {
3727 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3728 if (SHOW_INFO || Config.LOGV) {
3729 Log.v(TAG, " IntentFilter:");
3730 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3731 }
3732 removeFilter(intent);
3733 }
3734 }
3735
3736 @Override
3737 protected boolean allowFilterResult(
3738 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3739 ServiceInfo filterSi = filter.service.info;
3740 for (int i=dest.size()-1; i>=0; i--) {
3741 ServiceInfo destAi = dest.get(i).serviceInfo;
3742 if (destAi.name == filterSi.name
3743 && destAi.packageName == filterSi.packageName) {
3744 return false;
3745 }
3746 }
3747 return true;
3748 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 @Override
3751 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3752 int match) {
3753 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3754 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3755 return null;
3756 }
3757 final PackageParser.Service service = info.service;
3758 if (mSafeMode && (service.info.applicationInfo.flags
3759 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3760 return null;
3761 }
3762 final ResolveInfo res = new ResolveInfo();
3763 res.serviceInfo = PackageParser.generateServiceInfo(service,
3764 mFlags);
3765 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3766 res.filter = filter;
3767 }
3768 res.priority = info.getPriority();
3769 res.preferredOrder = service.owner.mPreferredOrder;
3770 //System.out.println("Result: " + res.activityInfo.className +
3771 // " = " + res.priority);
3772 res.match = match;
3773 res.isDefault = info.hasDefault;
3774 res.labelRes = info.labelRes;
3775 res.nonLocalizedLabel = info.nonLocalizedLabel;
3776 res.icon = info.icon;
3777 return res;
3778 }
3779
3780 @Override
3781 protected void sortResults(List<ResolveInfo> results) {
3782 Collections.sort(results, mResolvePrioritySorter);
3783 }
3784
3785 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003786 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003788 out.print(prefix); out.print(
3789 Integer.toHexString(System.identityHashCode(filter.service)));
3790 out.print(' ');
3791 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003792 }
3793
3794// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3795// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3796// final List<ResolveInfo> retList = Lists.newArrayList();
3797// while (i.hasNext()) {
3798// final ResolveInfo resolveInfo = (ResolveInfo) i;
3799// if (isEnabledLP(resolveInfo.serviceInfo)) {
3800// retList.add(resolveInfo);
3801// }
3802// }
3803// return retList;
3804// }
3805
3806 // Keys are String (activity class name), values are Activity.
3807 private final HashMap<ComponentName, PackageParser.Service> mServices
3808 = new HashMap<ComponentName, PackageParser.Service>();
3809 private int mFlags;
3810 };
3811
3812 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3813 new Comparator<ResolveInfo>() {
3814 public int compare(ResolveInfo r1, ResolveInfo r2) {
3815 int v1 = r1.priority;
3816 int v2 = r2.priority;
3817 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3818 if (v1 != v2) {
3819 return (v1 > v2) ? -1 : 1;
3820 }
3821 v1 = r1.preferredOrder;
3822 v2 = r2.preferredOrder;
3823 if (v1 != v2) {
3824 return (v1 > v2) ? -1 : 1;
3825 }
3826 if (r1.isDefault != r2.isDefault) {
3827 return r1.isDefault ? -1 : 1;
3828 }
3829 v1 = r1.match;
3830 v2 = r2.match;
3831 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3832 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3833 }
3834 };
3835
3836 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3837 new Comparator<ProviderInfo>() {
3838 public int compare(ProviderInfo p1, ProviderInfo p2) {
3839 final int v1 = p1.initOrder;
3840 final int v2 = p2.initOrder;
3841 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3842 }
3843 };
3844
3845 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3846 IActivityManager am = ActivityManagerNative.getDefault();
3847 if (am != null) {
3848 try {
3849 final Intent intent = new Intent(action,
3850 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3851 if (extras != null) {
3852 intent.putExtras(extras);
3853 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003854 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003855 am.broadcastIntent(
3856 null, intent,
3857 null, null, 0, null, null, null, false, false);
3858 } catch (RemoteException ex) {
3859 }
3860 }
3861 }
3862
3863 private final class AppDirObserver extends FileObserver {
3864 public AppDirObserver(String path, int mask, boolean isrom) {
3865 super(path, mask);
3866 mRootDir = path;
3867 mIsRom = isrom;
3868 }
3869
3870 public void onEvent(int event, String path) {
3871 String removedPackage = null;
3872 int removedUid = -1;
3873 String addedPackage = null;
3874 int addedUid = -1;
3875
3876 synchronized (mInstallLock) {
3877 String fullPathStr = null;
3878 File fullPath = null;
3879 if (path != null) {
3880 fullPath = new File(mRootDir, path);
3881 fullPathStr = fullPath.getPath();
3882 }
3883
3884 if (Config.LOGV) Log.v(
3885 TAG, "File " + fullPathStr + " changed: "
3886 + Integer.toHexString(event));
3887
3888 if (!isPackageFilename(path)) {
3889 if (Config.LOGV) Log.v(
3890 TAG, "Ignoring change of non-package file: " + fullPathStr);
3891 return;
3892 }
3893
3894 if ((event&REMOVE_EVENTS) != 0) {
3895 synchronized (mInstallLock) {
3896 PackageParser.Package p = mAppDirs.get(fullPathStr);
3897 if (p != null) {
3898 removePackageLI(p, true);
3899 removedPackage = p.applicationInfo.packageName;
3900 removedUid = p.applicationInfo.uid;
3901 }
3902 }
3903 }
3904
3905 if ((event&ADD_EVENTS) != 0) {
3906 PackageParser.Package p = mAppDirs.get(fullPathStr);
3907 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003908 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003909 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3910 PackageParser.PARSE_CHATTY |
3911 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08003912 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 if (p != null) {
3914 synchronized (mPackages) {
3915 grantPermissionsLP(p, false);
3916 }
3917 addedPackage = p.applicationInfo.packageName;
3918 addedUid = p.applicationInfo.uid;
3919 }
3920 }
3921 }
3922
3923 synchronized (mPackages) {
3924 mSettings.writeLP();
3925 }
3926 }
3927
3928 if (removedPackage != null) {
3929 Bundle extras = new Bundle(1);
3930 extras.putInt(Intent.EXTRA_UID, removedUid);
3931 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3932 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3933 }
3934 if (addedPackage != null) {
3935 Bundle extras = new Bundle(1);
3936 extras.putInt(Intent.EXTRA_UID, addedUid);
3937 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3938 }
3939 }
3940
3941 private final String mRootDir;
3942 private final boolean mIsRom;
3943 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 /* Called when a downloaded package installation has been confirmed by the user */
3946 public void installPackage(
3947 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003948 installPackage(packageURI, observer, flags, null);
3949 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003950
Jacek Surazski65e13172009-04-28 15:26:38 +02003951 /* Called when a downloaded package installation has been confirmed by the user */
3952 public void installPackage(
3953 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3954 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 mContext.enforceCallingOrSelfPermission(
3956 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003957
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003958 Message msg = mHandler.obtainMessage(INIT_COPY);
3959 msg.obj = createInstallArgs(packageURI, observer, flags, installerPackageName);
3960 mHandler.sendMessage(msg);
3961 }
3962
3963 private InstallArgs createInstallArgs(Uri packageURI, IPackageInstallObserver observer,
3964 int flags, String installerPackageName) {
3965 if (installOnSd(flags)) {
3966 return new SdInstallArgs(packageURI, observer, flags,
3967 installerPackageName);
3968 } else {
3969 return new FileInstallArgs(packageURI, observer, flags,
3970 installerPackageName);
3971 }
3972 }
3973
3974 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
3975 if (installOnSd(flags)) {
3976 return new SdInstallArgs(fullCodePath, fullResourcePath);
3977 } else {
3978 return new FileInstallArgs(fullCodePath, fullResourcePath);
3979 }
3980 }
3981
3982 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 // Queue up an async operation since the package installation may take a little while.
3984 mHandler.post(new Runnable() {
3985 public void run() {
3986 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003987 // Result object to be returned
3988 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003989 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003990 res.uid = -1;
3991 res.pkg = null;
3992 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003993 args.doPreInstall(res.returnCode);
3994 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003995 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003996 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003997 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003998 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004000 if (args.observer != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004001 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004002 args.observer.packageInstalled(res.name, res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 } catch (RemoteException e) {
4004 Log.i(TAG, "Observer no longer exists.");
4005 }
4006 }
4007 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
4008 // call appears in the synchronized block above.
4009 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4010 res.removedInfo.sendBroadcast(false, true);
4011 Bundle extras = new Bundle(1);
4012 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004013 final boolean update = res.removedInfo.removedPackage != null;
4014 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4016 }
4017 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
4018 res.pkg.applicationInfo.packageName,
4019 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004020 if (update) {
4021 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
4022 res.pkg.applicationInfo.packageName,
4023 extras);
4024 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004025 if (res.removedInfo.args != null) {
4026 // Remove the replaced package's older resources safely now
4027 synchronized (mInstallLock) {
4028 res.removedInfo.args.cleanUpResourcesLI();
4029 }
4030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 }
4032 Runtime.getRuntime().gc();
4033 }
4034 });
4035 }
4036
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004037 static abstract class InstallArgs {
4038 final IPackageInstallObserver observer;
4039 final int flags;
4040 final Uri packageURI;
4041 final String installerPackageName;
4042
4043 InstallArgs(Uri packageURI,
4044 IPackageInstallObserver observer, int flags,
4045 String installerPackageName) {
4046 this.packageURI = packageURI;
4047 this.flags = flags;
4048 this.observer = observer;
4049 this.installerPackageName = installerPackageName;
4050 }
4051
4052 abstract void createCopyFile();
4053 abstract int copyApk(IMediaContainerService imcs);
4054 abstract void doPreInstall(int status);
4055 abstract boolean doRename(int status, String pkgName, String oldCodePath);
4056 abstract void doPostInstall(int status);
4057 abstract String getCodePath();
4058 abstract String getResourcePath();
4059 // Need installer lock especially for dex file removal.
4060 abstract void cleanUpResourcesLI();
4061 }
4062
4063 class FileInstallArgs extends InstallArgs {
4064 File installDir;
4065 String codeFileName;
4066 String resourceFileName;
4067
4068 FileInstallArgs(Uri packageURI,
4069 IPackageInstallObserver observer, int flags,
4070 String installerPackageName) {
4071 super(packageURI, observer, flags, installerPackageName);
4072 }
4073
4074 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4075 super(null, null, 0, null);
4076 File codeFile = new File(fullCodePath);
4077 installDir = codeFile.getParentFile();
4078 codeFileName = fullCodePath;
4079 resourceFileName = fullResourcePath;
4080 }
4081
4082 void createCopyFile() {
4083 boolean fwdLocked = isFwdLocked(flags);
4084 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4085 codeFileName = createTempPackageFile(installDir).getPath();
4086 resourceFileName = getResourcePathFromCodePath();
4087 }
4088
4089 String getCodePath() {
4090 return codeFileName;
4091 }
4092
4093 int copyApk(IMediaContainerService imcs) {
4094 // Get a ParcelFileDescriptor to write to the output file
4095 File codeFile = new File(codeFileName);
4096 ParcelFileDescriptor out = null;
4097 try {
4098 out = ParcelFileDescriptor.open(codeFile,
4099 ParcelFileDescriptor.MODE_READ_WRITE);
4100 } catch (FileNotFoundException e) {
4101 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4102 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4103 }
4104 // Copy the resource now
4105 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4106 try {
4107 if (imcs.copyResource(packageURI, out)) {
4108 ret = PackageManager.INSTALL_SUCCEEDED;
4109 }
4110 } catch (RemoteException e) {
4111 } finally {
4112 try { if (out != null) out.close(); } catch (IOException e) {}
4113 }
4114 return ret;
4115 }
4116
4117 void doPreInstall(int status) {
4118 if (status != PackageManager.INSTALL_SUCCEEDED) {
4119 cleanUp();
4120 }
4121 }
4122
4123 boolean doRename(int status, final String pkgName, String oldCodePath) {
4124 if (status != PackageManager.INSTALL_SUCCEEDED) {
4125 cleanUp();
4126 return false;
4127 } else {
4128 // Rename based on packageName
4129 File codeFile = new File(getCodePath());
4130 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4131 File desFile = new File(installDir, apkName + ".apk");
4132 if (!codeFile.renameTo(desFile)) {
4133 return false;
4134 }
4135 // Reset paths since the file has been renamed.
4136 codeFileName = desFile.getPath();
4137 resourceFileName = getResourcePathFromCodePath();
4138 // Set permissions
4139 if (!setPermissions(pkgName)) {
4140 // Failed setting permissions.
4141 return false;
4142 }
4143 return true;
4144 }
4145 }
4146
4147 void doPostInstall(int status) {
4148 if (status != PackageManager.INSTALL_SUCCEEDED) {
4149 cleanUp();
4150 }
4151 }
4152
4153 String getResourcePath() {
4154 return resourceFileName;
4155 }
4156
4157 String getResourcePathFromCodePath() {
4158 String codePath = getCodePath();
4159 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4160 String apkNameOnly = getApkName(codePath);
4161 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4162 } else {
4163 return codePath;
4164 }
4165 }
4166
4167 private boolean cleanUp() {
4168 boolean ret = true;
4169 String sourceDir = getCodePath();
4170 String publicSourceDir = getResourcePath();
4171 if (sourceDir != null) {
4172 File sourceFile = new File(sourceDir);
4173 if (!sourceFile.exists()) {
4174 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4175 ret = false;
4176 }
4177 // Delete application's code and resources
4178 sourceFile.delete();
4179 }
4180 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4181 final File publicSourceFile = new File(publicSourceDir);
4182 if (!publicSourceFile.exists()) {
4183 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4184 }
4185 if (publicSourceFile.exists()) {
4186 publicSourceFile.delete();
4187 }
4188 }
4189 return ret;
4190 }
4191
4192 void cleanUpResourcesLI() {
4193 String sourceDir = getCodePath();
4194 if (cleanUp() && mInstaller != null) {
4195 int retCode = mInstaller.rmdex(sourceDir);
4196 if (retCode < 0) {
4197 Log.w(TAG, "Couldn't remove dex file for package: "
4198 + " at location "
4199 + sourceDir + ", retcode=" + retCode);
4200 // we don't consider this to be a failure of the core package deletion
4201 }
4202 }
4203 }
4204
4205 private boolean setPermissions(String pkgName) {
4206 // TODO Do this in a more elegant way later on. for now just a hack
4207 if (!isFwdLocked(flags)) {
4208 final int filePermissions =
4209 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4210 |FileUtils.S_IROTH;
4211 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4212 if (retCode != 0) {
4213 Log.e(TAG, "Couldn't set new package file permissions for " +
4214 getCodePath()
4215 + ". The return code was: " + retCode);
4216 // TODO Define new internal error
4217 return false;
4218 }
4219 return true;
4220 }
4221 return true;
4222 }
4223 }
4224
4225 class SdInstallArgs extends InstallArgs {
4226 String cid;
4227 String cachePath;
4228 static final String RES_FILE_NAME = "pkg.apk";
4229
4230 SdInstallArgs(Uri packageURI,
4231 IPackageInstallObserver observer, int flags,
4232 String installerPackageName) {
4233 super(packageURI, observer, flags, installerPackageName);
4234 }
4235
4236 SdInstallArgs(String fullCodePath, String fullResourcePath) {
4237 super(null, null, 0, null);
4238 // Extract cid from fullCodePath
4239 int eidx = fullCodePath.lastIndexOf("/");
4240 String subStr1 = fullCodePath.substring(0, eidx);
4241 int sidx = subStr1.lastIndexOf("/");
4242 cid = subStr1.substring(sidx+1, eidx);
4243 cachePath = subStr1;
4244 }
4245
4246 void createCopyFile() {
4247 cid = getTempContainerId();
4248 }
4249
4250 int copyApk(IMediaContainerService imcs) {
4251 try {
4252 cachePath = imcs.copyResourceToContainer(
4253 packageURI, cid,
4254 getEncryptKey(), RES_FILE_NAME);
4255 } catch (RemoteException e) {
4256 }
4257
4258 if (cachePath != null) {
4259 // Mount container once its created with system_uid
4260 cachePath = mountSdDir(cid, Process.SYSTEM_UID);
4261 }
4262 if (cachePath == null) {
4263 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4264 } else {
4265 return PackageManager.INSTALL_SUCCEEDED;
4266 }
4267 }
4268
4269 @Override
4270 String getCodePath() {
4271 return cachePath + "/" + RES_FILE_NAME;
4272 }
4273
4274 @Override
4275 String getResourcePath() {
4276 return cachePath + "/" + RES_FILE_NAME;
4277 }
4278
4279 void doPreInstall(int status) {
4280 if (status != PackageManager.INSTALL_SUCCEEDED) {
4281 // Destroy container
4282 destroySdDir(cid);
4283 }
4284 }
4285
4286 boolean doRename(int status, final String pkgName,
4287 String oldCodePath) {
4288 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
4289 // STOPSHIP TEMPORARY HACK FOR RENAME
4290 // Create new container at newCachePath
4291 String codePath = getCodePath();
4292 String newCachePath = null;
4293 final int CREATE_FAILED = 1;
4294 final int COPY_FAILED = 3;
4295 final int FINALIZE_FAILED = 5;
4296 final int PASS = 7;
4297 int errCode = CREATE_FAILED;
4298 if ((newCachePath = createSdDir(new File(codePath), newCacheId)) != null) {
4299 errCode = COPY_FAILED;
4300 // Copy file from codePath
4301 if (FileUtils.copyFile(new File(codePath), new File(newCachePath, RES_FILE_NAME))) {
4302 errCode = FINALIZE_FAILED;
4303 if (finalizeSdDir(newCacheId)) {
4304 errCode = PASS;
4305 }
4306 }
4307 }
4308 // Print error based on errCode
4309 String errMsg = "";
4310 switch (errCode) {
4311 case CREATE_FAILED:
4312 errMsg = "CREATE_FAILED";
4313 break;
4314 case COPY_FAILED:
4315 errMsg = "COPY_FAILED";
4316 destroySdDir(newCacheId);
4317 break;
4318 case FINALIZE_FAILED:
4319 errMsg = "FINALIZE_FAILED";
4320 destroySdDir(newCacheId);
4321 break;
4322 default:
4323 errMsg = "PASS";
4324 break;
4325 }
4326 // Destroy the temporary container
4327 destroySdDir(cid);
4328 Log.i(TAG, "Status: " + errMsg);
4329 if (errCode != PASS) {
4330 return false;
4331 }
4332 cid = newCacheId;
4333 cachePath = newCachePath;
4334
4335 return true;
4336 }
4337
4338 void doPostInstall(int status) {
4339 if (status != PackageManager.INSTALL_SUCCEEDED) {
4340 cleanUp();
4341 } else {
4342 // Unmount container
4343 // Rename and remount based on package name and new uid
4344 }
4345 }
4346
4347 private void cleanUp() {
4348 // Destroy secure container
4349 destroySdDir(cid);
4350 }
4351
4352 void cleanUpResourcesLI() {
4353 String sourceFile = getCodePath();
4354 // Remove dex file
4355 if (mInstaller != null) {
4356 int retCode = mInstaller.rmdex(sourceFile.toString());
4357 if (retCode < 0) {
4358 Log.w(TAG, "Couldn't remove dex file for package: "
4359 + " at location "
4360 + sourceFile.toString() + ", retcode=" + retCode);
4361 // we don't consider this to be a failure of the core package deletion
4362 }
4363 }
4364 cleanUp();
4365 }
4366 };
4367
4368 // Utility method used to create code paths based on package name and available index.
4369 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
4370 String idxStr = "";
4371 int idx = 1;
4372 if (oldCodePath != null) {
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004373 String subStr = oldCodePath;
4374 if (subStr.startsWith(prefix)) {
4375 subStr = subStr.substring(prefix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004376 }
Bjorn Bringert5fd5bfe2010-01-29 12:11:30 +00004377 if (subStr.endsWith(suffix)) {
4378 subStr = subStr.substring(0, subStr.length() - suffix.length());
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004379 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004380 if (subStr != null) {
4381 if (subStr.startsWith("-")) {
4382 subStr = subStr.substring(1);
4383 }
4384 try {
4385 idx = Integer.parseInt(subStr);
4386 if (idx <= 1) {
4387 idx++;
4388 } else {
4389 idx--;
4390 }
4391 } catch(NumberFormatException e) {
4392 }
4393 }
4394 }
4395 idxStr = "-" + Integer.toString(idx);
4396 return prefix + idxStr;
4397 }
4398
4399 // Utility method that returns the relative package path with respect
4400 // to the installation directory. Like say for /data/data/com.test-1.apk
4401 // string com.test-1 is returned.
4402 static String getApkName(String codePath) {
4403 if (codePath == null) {
4404 return null;
4405 }
4406 int sidx = codePath.lastIndexOf("/");
4407 int eidx = codePath.lastIndexOf(".");
4408 if (eidx == -1) {
4409 eidx = codePath.length();
4410 } else if (eidx == 0) {
4411 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
4412 return null;
4413 }
4414 return codePath.substring(sidx+1, eidx);
4415 }
4416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 class PackageInstalledInfo {
4418 String name;
4419 int uid;
4420 PackageParser.Package pkg;
4421 int returnCode;
4422 PackageRemovedInfo removedInfo;
4423 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 /*
4426 * Install a non-existing package.
4427 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004428 private void installNewPackageLI(PackageParser.Package pkg,
4429 int parseFlags,
4430 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004431 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08004433 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004434 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08004435
4436 if (useEncryptedFilesystemForPackage(pkg)) {
4437 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
4438 } else {
4439 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
4440 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 res.name = pkgName;
4442 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004443 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004445 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 + " without first uninstalling.");
4447 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4448 return;
4449 }
4450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004452 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004454 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4456 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4457 }
4458 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004459 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004460 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 res);
4462 // delete the partially installed application. the data directory will have to be
4463 // restored if it was already existing
4464 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4465 // remove package from internal structures. Note that we want deletePackageX to
4466 // delete the package data and cache directories that it created in
4467 // scanPackageLocked, unless those directories existed before we even tried to
4468 // install.
4469 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004470 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
4472 res.removedInfo);
4473 }
4474 }
4475 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004476
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004477 private void replacePackageLI(PackageParser.Package pkg,
4478 int parseFlags,
4479 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004480 String installerPackageName, PackageInstalledInfo res) {
4481
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004482 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004483 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 // First find the old package info and check signatures
4485 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004486 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004487 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
4488 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4490 return;
4491 }
4492 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004493 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004494 if(sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004495 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004497 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 }
4499 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004501 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004502 PackageParser.Package pkg,
4503 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004504 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 PackageParser.Package newPackage = null;
4506 String pkgName = deletedPackage.packageName;
4507 boolean deletedPkg = true;
4508 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004509
Jacek Surazski65e13172009-04-28 15:26:38 +02004510 String oldInstallerPackageName = null;
4511 synchronized (mPackages) {
4512 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
4513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004514
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004515 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004517 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 res.removedInfo)) {
4519 // If the existing package was'nt successfully deleted
4520 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4521 deletedPkg = false;
4522 } else {
4523 // Successfully deleted the old package. Now proceed with re-installation
4524 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004525 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004527 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4529 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08004530 }
4531 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004532 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004533 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004534 res);
4535 updatedSettings = true;
4536 }
4537 }
4538
4539 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4540 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004541 // were keeping around in case we needed them (see below) can now be deleted.
4542 // This info will be set on the res.removedInfo to clean up later on as post
4543 // install action.
4544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004545 //update signature on the new package setting
4546 //this should always succeed, since we checked the
4547 //signature earlier.
4548 synchronized(mPackages) {
4549 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4550 parseFlags, true);
4551 }
4552 } else {
4553 // remove package from internal structures. Note that we want deletePackageX to
4554 // delete the package data and cache directories that it created in
4555 // scanPackageLocked, unless those directories existed before we even tried to
4556 // install.
4557 if(updatedSettings) {
4558 deletePackageLI(
4559 pkgName, true,
4560 PackageManager.DONT_DELETE_DATA,
4561 res.removedInfo);
4562 }
4563 // Since we failed to install the new package we need to restore the old
4564 // package that we deleted.
4565 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004566 File restoreFile = new File(deletedPackage.mPath);
4567 if (restoreFile == null) {
4568 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4569 return;
4570 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004571 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4572 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004573 // Parse old package
4574 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
4575 scanPackageLI(restoreFile, parseFlags, scanMode);
4576 synchronized (mPackages) {
4577 grantPermissionsLP(deletedPackage, false);
4578 mSettings.writeLP();
4579 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004580 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4581 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 }
4584 }
4585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004588 PackageParser.Package pkg,
4589 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004590 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004591 PackageParser.Package newPackage = null;
4592 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004593 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 PackageParser.PARSE_IS_SYSTEM;
4595 String packageName = deletedPackage.packageName;
4596 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4597 if (packageName == null) {
4598 Log.w(TAG, "Attempt to delete null packageName.");
4599 return;
4600 }
4601 PackageParser.Package oldPkg;
4602 PackageSetting oldPkgSetting;
4603 synchronized (mPackages) {
4604 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004605 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4607 (oldPkgSetting == null)) {
4608 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4609 return;
4610 }
4611 }
4612 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4613 res.removedInfo.removedPackage = packageName;
4614 // Remove existing system package
4615 removePackageLI(oldPkg, true);
4616 synchronized (mPackages) {
4617 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4618 }
4619
4620 // Successfully disabled the old package. Now proceed with re-installation
4621 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4622 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004623 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004624 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004625 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4627 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4628 }
4629 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004630 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 updatedSettings = true;
4632 }
4633
4634 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4635 //update signature on the new package setting
4636 //this should always succeed, since we checked the
4637 //signature earlier.
4638 synchronized(mPackages) {
4639 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4640 parseFlags, true);
4641 }
4642 } else {
4643 // Re installation failed. Restore old information
4644 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004645 if (newPackage != null) {
4646 removePackageLI(newPackage, true);
4647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004648 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004649 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004651 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 // Restore the old system information in Settings
4653 synchronized(mPackages) {
4654 if(updatedSettings) {
4655 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004656 mSettings.setInstallerPackageName(packageName,
4657 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 }
4659 mSettings.writeLP();
4660 }
4661 }
4662 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004663
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004664 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004665 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004666 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004667 synchronized (mPackages) {
4668 //write settings. the installStatus will be incomplete at this stage.
4669 //note that the new package setting would have already been
4670 //added to mPackages. It hasn't been persisted yet.
4671 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4672 mSettings.writeLP();
4673 }
4674
4675 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004676 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4677 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004679 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004680 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4681 return;
4682 }
4683 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004684 res.returnCode = setPermissionsLI(newPackage);
4685 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4686 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004688 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004689 }
4690 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4691 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004692 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 }
4694 }
4695
4696 synchronized (mPackages) {
4697 grantPermissionsLP(newPackage, true);
4698 res.name = pkgName;
4699 res.uid = newPackage.applicationInfo.uid;
4700 res.pkg = newPackage;
4701 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004702 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004703 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4704 //to update install status
4705 mSettings.writeLP();
4706 }
4707 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004708
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004709 private void installPackageLI(InstallArgs args,
4710 boolean newInstall, PackageInstalledInfo res) {
4711 int pFlags = args.flags;
4712 String installerPackageName = args.installerPackageName;
4713 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004714 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
4715 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004716 boolean replacingExistingPackage = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004717 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
4718 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004719 // Result object to be returned
4720 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4721
4722 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004723 // Retrieve PackageSettings and parse package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004724 int parseFlags = PackageParser.PARSE_CHATTY |
4725 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
4726 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004727 parseFlags |= mDefParseFlags;
4728 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4729 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004731 null, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 if (pkg == null) {
4733 res.returnCode = pp.getParseError();
4734 break main_flow;
4735 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004736 String pkgName = res.name = pkg.packageName;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004737 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4738 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4739 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4740 break main_flow;
4741 }
4742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4744 res.returnCode = pp.getParseError();
4745 break main_flow;
4746 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004747
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004748 // Get rid of all references to package scan path via parser.
4749 pp = null;
4750 String oldCodePath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004751 synchronized (mPackages) {
4752 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004753 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004754 && mPackages.containsKey(pkgName)) {
4755 replacingExistingPackage = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004756 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004757 }
4758 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004759
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004760 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
4761 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4762 break main_flow;
4763 }
4764 // TODO rename pkg.mScanPath In scanPackageLI let it just set values based on mScanPath
4765 pkg.applicationInfo.sourceDir = pkg.mScanPath= pkg.mPath = args.getCodePath();
4766 pkg.applicationInfo.publicSourceDir = args.getResourcePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004767 if(replacingExistingPackage) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004768 replacePackageLI(pkg, parseFlags, scanMode,
4769 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004771 installNewPackageLI(pkg, parseFlags, scanMode,
4772 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 }
4774 } finally {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004775 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004777 }
4778 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004779
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004780 private int setPermissionsLI(PackageParser.Package newPackage) {
4781 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004782 int retCode = 0;
4783 // TODO Gross hack but fix later. Ideally move this to be a post installation
4784 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004785 if ((newPackage.applicationInfo.flags
4786 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
4787 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004788 try {
4789 extractPublicFiles(newPackage, destResourceFile);
4790 } catch (IOException e) {
4791 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4792 " forward-locked app.");
4793 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4794 } finally {
4795 //TODO clean up the extracted public files
4796 }
4797 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004798 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 newPackage.applicationInfo.uid);
4800 } else {
4801 final int filePermissions =
4802 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004803 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004804 newPackage.applicationInfo.uid);
4805 }
4806 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004807 // The permissions on the resource file was set when it was copied for
4808 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004811 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004812 Log.e(TAG, "Couldn't set new package file permissions for " +
4813 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004814 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004815 // TODO Define new internal error
4816 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 }
4818 return PackageManager.INSTALL_SUCCEEDED;
4819 }
4820
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004821 private boolean isForwardLocked(PackageParser.Package pkg) {
4822 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 }
4824
4825 private void extractPublicFiles(PackageParser.Package newPackage,
4826 File publicZipFile) throws IOException {
4827 final ZipOutputStream publicZipOutStream =
4828 new ZipOutputStream(new FileOutputStream(publicZipFile));
4829 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4830
4831 // Copy manifest, resources.arsc and res directory to public zip
4832
4833 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4834 while (privateZipEntries.hasMoreElements()) {
4835 final ZipEntry zipEntry = privateZipEntries.nextElement();
4836 final String zipEntryName = zipEntry.getName();
4837 if ("AndroidManifest.xml".equals(zipEntryName)
4838 || "resources.arsc".equals(zipEntryName)
4839 || zipEntryName.startsWith("res/")) {
4840 try {
4841 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4842 } catch (IOException e) {
4843 try {
4844 publicZipOutStream.close();
4845 throw e;
4846 } finally {
4847 publicZipFile.delete();
4848 }
4849 }
4850 }
4851 }
4852
4853 publicZipOutStream.close();
4854 FileUtils.setPermissions(
4855 publicZipFile.getAbsolutePath(),
4856 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4857 -1, -1);
4858 }
4859
4860 private static void copyZipEntry(ZipEntry zipEntry,
4861 ZipFile inZipFile,
4862 ZipOutputStream outZipStream) throws IOException {
4863 byte[] buffer = new byte[4096];
4864 int num;
4865
4866 ZipEntry newEntry;
4867 if (zipEntry.getMethod() == ZipEntry.STORED) {
4868 // Preserve the STORED method of the input entry.
4869 newEntry = new ZipEntry(zipEntry);
4870 } else {
4871 // Create a new entry so that the compressed len is recomputed.
4872 newEntry = new ZipEntry(zipEntry.getName());
4873 }
4874 outZipStream.putNextEntry(newEntry);
4875
4876 InputStream data = inZipFile.getInputStream(zipEntry);
4877 while ((num = data.read(buffer)) > 0) {
4878 outZipStream.write(buffer, 0, num);
4879 }
4880 outZipStream.flush();
4881 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004883 private void deleteTempPackageFiles() {
4884 FilenameFilter filter = new FilenameFilter() {
4885 public boolean accept(File dir, String name) {
4886 return name.startsWith("vmdl") && name.endsWith(".tmp");
4887 }
4888 };
4889 String tmpFilesList[] = mAppInstallDir.list(filter);
4890 if(tmpFilesList == null) {
4891 return;
4892 }
4893 for(int i = 0; i < tmpFilesList.length; i++) {
4894 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4895 tmpFile.delete();
4896 }
4897 }
4898
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004899 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900 File tmpPackageFile;
4901 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004902 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004903 } catch (IOException e) {
4904 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4905 return null;
4906 }
4907 try {
4908 FileUtils.setPermissions(
4909 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4910 -1, -1);
4911 } catch (IOException e) {
4912 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4913 return null;
4914 }
4915 return tmpPackageFile;
4916 }
4917
4918 public void deletePackage(final String packageName,
4919 final IPackageDeleteObserver observer,
4920 final int flags) {
4921 mContext.enforceCallingOrSelfPermission(
4922 android.Manifest.permission.DELETE_PACKAGES, null);
4923 // Queue up an async operation since the package deletion may take a little while.
4924 mHandler.post(new Runnable() {
4925 public void run() {
4926 mHandler.removeCallbacks(this);
4927 final boolean succeded = deletePackageX(packageName, true, true, flags);
4928 if (observer != null) {
4929 try {
4930 observer.packageDeleted(succeded);
4931 } catch (RemoteException e) {
4932 Log.i(TAG, "Observer no longer exists.");
4933 } //end catch
4934 } //end if
4935 } //end run
4936 });
4937 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 /**
4940 * This method is an internal method that could be get invoked either
4941 * to delete an installed package or to clean up a failed installation.
4942 * After deleting an installed package, a broadcast is sent to notify any
4943 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004944 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004945 * installation wouldn't have sent the initial broadcast either
4946 * The key steps in deleting a package are
4947 * deleting the package information in internal structures like mPackages,
4948 * deleting the packages base directories through installd
4949 * updating mSettings to reflect current status
4950 * persisting settings for later use
4951 * sending a broadcast if necessary
4952 */
4953
4954 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4955 boolean deleteCodeAndResources, int flags) {
4956 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004957 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004958
4959 synchronized (mInstallLock) {
4960 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4961 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004964 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4965 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4966
4967 // If the removed package was a system update, the old system packaged
4968 // was re-enabled; we need to broadcast this information
4969 if (systemUpdate) {
4970 Bundle extras = new Bundle(1);
4971 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4972 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4973
4974 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4975 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004978 // Delete the resources here after sending the broadcast to let
4979 // other processes clean up before deleting resources.
4980 synchronized (mInstallLock) {
4981 if (info.args != null) {
4982 info.args.cleanUpResourcesLI();
4983 }
4984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 return res;
4986 }
4987
4988 static class PackageRemovedInfo {
4989 String removedPackage;
4990 int uid = -1;
4991 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004992 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004993 // Clean up resources deleted packages.
4994 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07004995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004996 void sendBroadcast(boolean fullRemove, boolean replacing) {
4997 Bundle extras = new Bundle(1);
4998 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4999 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
5000 if (replacing) {
5001 extras.putBoolean(Intent.EXTRA_REPLACING, true);
5002 }
5003 if (removedPackage != null) {
5004 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
5005 }
5006 if (removedUid >= 0) {
5007 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5008 }
5009 }
5010 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005012 /*
5013 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5014 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005015 * 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 -08005016 * delete a partially installed application.
5017 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005018 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 int flags) {
5020 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005021 if (outInfo != null) {
5022 outInfo.removedPackage = packageName;
5023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 removePackageLI(p, true);
5025 // Retrieve object to delete permissions for shared user later on
5026 PackageSetting deletedPs;
5027 synchronized (mPackages) {
5028 deletedPs = mSettings.mPackages.get(packageName);
5029 }
5030 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005031 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005033 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 if (retCode < 0) {
5035 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5036 + packageName + ", retcode=" + retCode);
5037 // we don't consider this to be a failure of the core package deletion
5038 }
5039 } else {
5040 //for emulator
5041 PackageParser.Package pkg = mPackages.get(packageName);
5042 File dataDir = new File(pkg.applicationInfo.dataDir);
5043 dataDir.delete();
5044 }
5045 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005046 if (outInfo != null) {
5047 outInfo.removedUid = mSettings.removePackageLP(packageName);
5048 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005049 }
5050 }
5051 synchronized (mPackages) {
5052 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5053 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005054 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 }
5056 // Save settings now
5057 mSettings.writeLP ();
5058 }
5059 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005061 /*
5062 * Tries to delete system package.
5063 */
5064 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005065 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005066 ApplicationInfo applicationInfo = p.applicationInfo;
5067 //applicable for non-partially installed applications only
5068 if (applicationInfo == null) {
5069 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5070 return false;
5071 }
5072 PackageSetting ps = null;
5073 // Confirm if the system package has been updated
5074 // An updated system app can be deleted. This will also have to restore
5075 // the system pkg from system partition
5076 synchronized (mPackages) {
5077 ps = mSettings.getDisabledSystemPkg(p.packageName);
5078 }
5079 if (ps == null) {
5080 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5081 return false;
5082 } else {
5083 Log.i(TAG, "Deleting system pkg from data partition");
5084 }
5085 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005086 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005087 boolean deleteCodeAndResources = false;
5088 if (ps.versionCode < p.mVersionCode) {
5089 // Delete code and resources for downgrades
5090 deleteCodeAndResources = true;
5091 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5092 flags &= ~PackageManager.DONT_DELETE_DATA;
5093 }
5094 } else {
5095 // Preserve data by setting flag
5096 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5097 flags |= PackageManager.DONT_DELETE_DATA;
5098 }
5099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5101 if (!ret) {
5102 return false;
5103 }
5104 synchronized (mPackages) {
5105 // Reinstate the old system package
5106 mSettings.enableSystemPackageLP(p.packageName);
5107 }
5108 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005109 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005111 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005113 if (newPkg == null) {
5114 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5115 return false;
5116 }
5117 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005118 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 mSettings.writeLP();
5120 }
5121 return true;
5122 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005124 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5125 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5126 ApplicationInfo applicationInfo = p.applicationInfo;
5127 if (applicationInfo == null) {
5128 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5129 return false;
5130 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005131 if (outInfo != null) {
5132 outInfo.uid = applicationInfo.uid;
5133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134
5135 // Delete package data from internal structures and also remove data if flag is set
5136 removePackageDataLI(p, outInfo, flags);
5137
5138 // Delete application code and resources
5139 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005140 // TODO can pick up from PackageSettings as well
5141 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
5142 PackageManager.INSTALL_ON_SDCARD : 0;
5143 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5144 PackageManager.INSTALL_FORWARD_LOCK : 0;
5145 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005146 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 }
5148 return true;
5149 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 /*
5152 * This method handles package deletion in general
5153 */
5154 private boolean deletePackageLI(String packageName,
5155 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5156 if (packageName == null) {
5157 Log.w(TAG, "Attempt to delete null packageName.");
5158 return false;
5159 }
5160 PackageParser.Package p;
5161 boolean dataOnly = false;
5162 synchronized (mPackages) {
5163 p = mPackages.get(packageName);
5164 if (p == null) {
5165 //this retrieves partially installed apps
5166 dataOnly = true;
5167 PackageSetting ps = mSettings.mPackages.get(packageName);
5168 if (ps == null) {
5169 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5170 return false;
5171 }
5172 p = ps.pkg;
5173 }
5174 }
5175 if (p == null) {
5176 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5177 return false;
5178 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005180 if (dataOnly) {
5181 // Delete application data first
5182 removePackageDataLI(p, outInfo, flags);
5183 return true;
5184 }
5185 // At this point the package should have ApplicationInfo associated with it
5186 if (p.applicationInfo == null) {
5187 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5188 return false;
5189 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005190 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005191 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5192 Log.i(TAG, "Removing system package:"+p.packageName);
5193 // When an updated system application is deleted we delete the existing resources as well and
5194 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005195 ret = deleteSystemPackageLI(p, flags, outInfo);
5196 } else {
5197 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005198 // Kill application pre-emptively especially for apps on sd.
5199 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005200 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005201 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005202 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005205 public void clearApplicationUserData(final String packageName,
5206 final IPackageDataObserver observer) {
5207 mContext.enforceCallingOrSelfPermission(
5208 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
5209 // Queue up an async operation since the package deletion may take a little while.
5210 mHandler.post(new Runnable() {
5211 public void run() {
5212 mHandler.removeCallbacks(this);
5213 final boolean succeeded;
5214 synchronized (mInstallLock) {
5215 succeeded = clearApplicationUserDataLI(packageName);
5216 }
5217 if (succeeded) {
5218 // invoke DeviceStorageMonitor's update method to clear any notifications
5219 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
5220 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
5221 if (dsm != null) {
5222 dsm.updateMemory();
5223 }
5224 }
5225 if(observer != null) {
5226 try {
5227 observer.onRemoveCompleted(packageName, succeeded);
5228 } catch (RemoteException e) {
5229 Log.i(TAG, "Observer no longer exists.");
5230 }
5231 } //end if observer
5232 } //end run
5233 });
5234 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005236 private boolean clearApplicationUserDataLI(String packageName) {
5237 if (packageName == null) {
5238 Log.w(TAG, "Attempt to delete null packageName.");
5239 return false;
5240 }
5241 PackageParser.Package p;
5242 boolean dataOnly = false;
5243 synchronized (mPackages) {
5244 p = mPackages.get(packageName);
5245 if(p == null) {
5246 dataOnly = true;
5247 PackageSetting ps = mSettings.mPackages.get(packageName);
5248 if((ps == null) || (ps.pkg == null)) {
5249 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5250 return false;
5251 }
5252 p = ps.pkg;
5253 }
5254 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005255 boolean useEncryptedFSDir = false;
5256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005257 if(!dataOnly) {
5258 //need to check this only for fully installed applications
5259 if (p == null) {
5260 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5261 return false;
5262 }
5263 final ApplicationInfo applicationInfo = p.applicationInfo;
5264 if (applicationInfo == null) {
5265 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5266 return false;
5267 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005268 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005269 }
5270 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005271 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 if (retCode < 0) {
5273 Log.w(TAG, "Couldn't remove cache files for package: "
5274 + packageName);
5275 return false;
5276 }
5277 }
5278 return true;
5279 }
5280
5281 public void deleteApplicationCacheFiles(final String packageName,
5282 final IPackageDataObserver observer) {
5283 mContext.enforceCallingOrSelfPermission(
5284 android.Manifest.permission.DELETE_CACHE_FILES, null);
5285 // Queue up an async operation since the package deletion may take a little while.
5286 mHandler.post(new Runnable() {
5287 public void run() {
5288 mHandler.removeCallbacks(this);
5289 final boolean succeded;
5290 synchronized (mInstallLock) {
5291 succeded = deleteApplicationCacheFilesLI(packageName);
5292 }
5293 if(observer != null) {
5294 try {
5295 observer.onRemoveCompleted(packageName, succeded);
5296 } catch (RemoteException e) {
5297 Log.i(TAG, "Observer no longer exists.");
5298 }
5299 } //end if observer
5300 } //end run
5301 });
5302 }
5303
5304 private boolean deleteApplicationCacheFilesLI(String packageName) {
5305 if (packageName == null) {
5306 Log.w(TAG, "Attempt to delete null packageName.");
5307 return false;
5308 }
5309 PackageParser.Package p;
5310 synchronized (mPackages) {
5311 p = mPackages.get(packageName);
5312 }
5313 if (p == null) {
5314 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5315 return false;
5316 }
5317 final ApplicationInfo applicationInfo = p.applicationInfo;
5318 if (applicationInfo == null) {
5319 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5320 return false;
5321 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005322 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005324 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005325 if (retCode < 0) {
5326 Log.w(TAG, "Couldn't remove cache files for package: "
5327 + packageName);
5328 return false;
5329 }
5330 }
5331 return true;
5332 }
5333
5334 public void getPackageSizeInfo(final String packageName,
5335 final IPackageStatsObserver observer) {
5336 mContext.enforceCallingOrSelfPermission(
5337 android.Manifest.permission.GET_PACKAGE_SIZE, null);
5338 // Queue up an async operation since the package deletion may take a little while.
5339 mHandler.post(new Runnable() {
5340 public void run() {
5341 mHandler.removeCallbacks(this);
5342 PackageStats lStats = new PackageStats(packageName);
5343 final boolean succeded;
5344 synchronized (mInstallLock) {
5345 succeded = getPackageSizeInfoLI(packageName, lStats);
5346 }
5347 if(observer != null) {
5348 try {
5349 observer.onGetStatsCompleted(lStats, succeded);
5350 } catch (RemoteException e) {
5351 Log.i(TAG, "Observer no longer exists.");
5352 }
5353 } //end if observer
5354 } //end run
5355 });
5356 }
5357
5358 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
5359 if (packageName == null) {
5360 Log.w(TAG, "Attempt to get size of null packageName.");
5361 return false;
5362 }
5363 PackageParser.Package p;
5364 boolean dataOnly = false;
5365 synchronized (mPackages) {
5366 p = mPackages.get(packageName);
5367 if(p == null) {
5368 dataOnly = true;
5369 PackageSetting ps = mSettings.mPackages.get(packageName);
5370 if((ps == null) || (ps.pkg == null)) {
5371 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5372 return false;
5373 }
5374 p = ps.pkg;
5375 }
5376 }
5377 String publicSrcDir = null;
5378 if(!dataOnly) {
5379 final ApplicationInfo applicationInfo = p.applicationInfo;
5380 if (applicationInfo == null) {
5381 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5382 return false;
5383 }
5384 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
5385 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005386 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 if (mInstaller != null) {
5388 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08005389 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 if (res < 0) {
5391 return false;
5392 } else {
5393 return true;
5394 }
5395 }
5396 return true;
5397 }
5398
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 public void addPackageToPreferred(String packageName) {
5401 mContext.enforceCallingOrSelfPermission(
5402 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005403 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 }
5405
5406 public void removePackageFromPreferred(String packageName) {
5407 mContext.enforceCallingOrSelfPermission(
5408 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005409 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 }
5411
5412 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005413 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 }
5415
5416 public void addPreferredActivity(IntentFilter filter, int match,
5417 ComponentName[] set, ComponentName activity) {
5418 mContext.enforceCallingOrSelfPermission(
5419 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5420
5421 synchronized (mPackages) {
5422 Log.i(TAG, "Adding preferred activity " + activity + ":");
5423 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5424 mSettings.mPreferredActivities.addFilter(
5425 new PreferredActivity(filter, match, set, activity));
5426 mSettings.writeLP();
5427 }
5428 }
5429
Satish Sampath8dbe6122009-06-02 23:35:54 +01005430 public void replacePreferredActivity(IntentFilter filter, int match,
5431 ComponentName[] set, ComponentName activity) {
5432 mContext.enforceCallingOrSelfPermission(
5433 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5434 if (filter.countActions() != 1) {
5435 throw new IllegalArgumentException(
5436 "replacePreferredActivity expects filter to have only 1 action.");
5437 }
5438 if (filter.countCategories() != 1) {
5439 throw new IllegalArgumentException(
5440 "replacePreferredActivity expects filter to have only 1 category.");
5441 }
5442 if (filter.countDataAuthorities() != 0
5443 || filter.countDataPaths() != 0
5444 || filter.countDataSchemes() != 0
5445 || filter.countDataTypes() != 0) {
5446 throw new IllegalArgumentException(
5447 "replacePreferredActivity expects filter to have no data authorities, " +
5448 "paths, schemes or types.");
5449 }
5450 synchronized (mPackages) {
5451 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5452 String action = filter.getAction(0);
5453 String category = filter.getCategory(0);
5454 while (it.hasNext()) {
5455 PreferredActivity pa = it.next();
5456 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5457 it.remove();
5458 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5459 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5460 }
5461 }
5462 addPreferredActivity(filter, match, set, activity);
5463 }
5464 }
5465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005466 public void clearPackagePreferredActivities(String packageName) {
5467 mContext.enforceCallingOrSelfPermission(
5468 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5469
5470 synchronized (mPackages) {
5471 if (clearPackagePreferredActivitiesLP(packageName)) {
5472 mSettings.writeLP();
5473 }
5474 }
5475 }
5476
5477 boolean clearPackagePreferredActivitiesLP(String packageName) {
5478 boolean changed = false;
5479 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5480 while (it.hasNext()) {
5481 PreferredActivity pa = it.next();
5482 if (pa.mActivity.getPackageName().equals(packageName)) {
5483 it.remove();
5484 changed = true;
5485 }
5486 }
5487 return changed;
5488 }
5489
5490 public int getPreferredActivities(List<IntentFilter> outFilters,
5491 List<ComponentName> outActivities, String packageName) {
5492
5493 int num = 0;
5494 synchronized (mPackages) {
5495 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5496 while (it.hasNext()) {
5497 PreferredActivity pa = it.next();
5498 if (packageName == null
5499 || pa.mActivity.getPackageName().equals(packageName)) {
5500 if (outFilters != null) {
5501 outFilters.add(new IntentFilter(pa));
5502 }
5503 if (outActivities != null) {
5504 outActivities.add(pa.mActivity);
5505 }
5506 }
5507 }
5508 }
5509
5510 return num;
5511 }
5512
5513 public void setApplicationEnabledSetting(String appPackageName,
5514 int newState, int flags) {
5515 setEnabledSetting(appPackageName, null, newState, flags);
5516 }
5517
5518 public void setComponentEnabledSetting(ComponentName componentName,
5519 int newState, int flags) {
5520 setEnabledSetting(componentName.getPackageName(),
5521 componentName.getClassName(), newState, flags);
5522 }
5523
5524 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005525 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5527 || newState == COMPONENT_ENABLED_STATE_ENABLED
5528 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5529 throw new IllegalArgumentException("Invalid new component state: "
5530 + newState);
5531 }
5532 PackageSetting pkgSetting;
5533 final int uid = Binder.getCallingUid();
5534 final int permission = mContext.checkCallingPermission(
5535 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5536 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005537 boolean sendNow = false;
5538 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005539 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005541 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005542 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005543 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005545 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005547 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 }
5549 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005550 "Unknown component: " + packageName
5551 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 }
5553 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5554 throw new SecurityException(
5555 "Permission Denial: attempt to change component state from pid="
5556 + Binder.getCallingPid()
5557 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5558 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005559 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005560 // We're dealing with an application/package level state change
5561 pkgSetting.enabled = newState;
5562 } else {
5563 // We're dealing with a component level state change
5564 switch (newState) {
5565 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005566 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 break;
5568 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005569 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005570 break;
5571 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005572 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005573 break;
5574 default:
5575 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005576 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 }
5578 }
5579 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005580 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005581 components = mPendingBroadcasts.get(packageName);
5582 boolean newPackage = components == null;
5583 if (newPackage) {
5584 components = new ArrayList<String>();
5585 }
5586 if (!components.contains(componentName)) {
5587 components.add(componentName);
5588 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005589 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5590 sendNow = true;
5591 // Purge entry from pending broadcast list if another one exists already
5592 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005593 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005594 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005595 if (newPackage) {
5596 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005597 }
5598 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5599 // Schedule a message
5600 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5601 }
5602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005605 long callingId = Binder.clearCallingIdentity();
5606 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005607 if (sendNow) {
5608 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005609 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005610 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 } finally {
5612 Binder.restoreCallingIdentity(callingId);
5613 }
5614 }
5615
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005616 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005617 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5618 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5619 + " components=" + componentNames);
5620 Bundle extras = new Bundle(4);
5621 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5622 String nameList[] = new String[componentNames.size()];
5623 componentNames.toArray(nameList);
5624 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005625 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5626 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005627 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005628 }
5629
Jacek Surazski65e13172009-04-28 15:26:38 +02005630 public String getInstallerPackageName(String packageName) {
5631 synchronized (mPackages) {
5632 PackageSetting pkg = mSettings.mPackages.get(packageName);
5633 if (pkg == null) {
5634 throw new IllegalArgumentException("Unknown package: " + packageName);
5635 }
5636 return pkg.installerPackageName;
5637 }
5638 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005640 public int getApplicationEnabledSetting(String appPackageName) {
5641 synchronized (mPackages) {
5642 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5643 if (pkg == null) {
5644 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5645 }
5646 return pkg.enabled;
5647 }
5648 }
5649
5650 public int getComponentEnabledSetting(ComponentName componentName) {
5651 synchronized (mPackages) {
5652 final String packageNameStr = componentName.getPackageName();
5653 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5654 if (pkg == null) {
5655 throw new IllegalArgumentException("Unknown component: " + componentName);
5656 }
5657 final String classNameStr = componentName.getClassName();
5658 return pkg.currentEnabledStateLP(classNameStr);
5659 }
5660 }
5661
5662 public void enterSafeMode() {
5663 if (!mSystemReady) {
5664 mSafeMode = true;
5665 }
5666 }
5667
5668 public void systemReady() {
5669 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005670
5671 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005672 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005673 mContext.getContentResolver(),
5674 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005675 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005676 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005677 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 }
5680
5681 public boolean isSafeMode() {
5682 return mSafeMode;
5683 }
5684
5685 public boolean hasSystemUidErrors() {
5686 return mHasSystemUidErrors;
5687 }
5688
5689 static String arrayToString(int[] array) {
5690 StringBuffer buf = new StringBuffer(128);
5691 buf.append('[');
5692 if (array != null) {
5693 for (int i=0; i<array.length; i++) {
5694 if (i > 0) buf.append(", ");
5695 buf.append(array[i]);
5696 }
5697 }
5698 buf.append(']');
5699 return buf.toString();
5700 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 @Override
5703 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5704 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5705 != PackageManager.PERMISSION_GRANTED) {
5706 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5707 + Binder.getCallingPid()
5708 + ", uid=" + Binder.getCallingUid()
5709 + " without permission "
5710 + android.Manifest.permission.DUMP);
5711 return;
5712 }
5713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 synchronized (mPackages) {
5715 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005716 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 pw.println(" ");
5718 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005719 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005720 pw.println(" ");
5721 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005722 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005723 pw.println(" ");
5724 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005725 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005727 pw.println("Permissions:");
5728 {
5729 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005730 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5731 pw.print(Integer.toHexString(System.identityHashCode(p)));
5732 pw.println("):");
5733 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5734 pw.print(" uid="); pw.print(p.uid);
5735 pw.print(" gids="); pw.print(arrayToString(p.gids));
5736 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005737 }
5738 }
5739 pw.println(" ");
5740 pw.println("Packages:");
5741 {
5742 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005743 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5744 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5745 pw.println("):");
5746 pw.print(" userId="); pw.print(ps.userId);
5747 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5748 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5749 pw.print(" pkg="); pw.println(ps.pkg);
5750 pw.print(" codePath="); pw.println(ps.codePathString);
5751 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005753 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005754 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005755 pw.print(" supportsScreens=[");
5756 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005757 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005758 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005759 if (!first) pw.print(", ");
5760 first = false;
5761 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005762 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005763 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005764 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005765 if (!first) pw.print(", ");
5766 first = false;
5767 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005768 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005769 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005770 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005771 if (!first) pw.print(", ");
5772 first = false;
5773 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005774 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005775 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005776 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005777 if (!first) pw.print(", ");
5778 first = false;
5779 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005781 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005782 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5783 if (!first) pw.print(", ");
5784 first = false;
5785 pw.print("anyDensity");
5786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005788 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005789 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5790 pw.print(" signatures="); pw.println(ps.signatures);
5791 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5792 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5793 pw.print(" installStatus="); pw.print(ps.installStatus);
5794 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005795 if (ps.disabledComponents.size() > 0) {
5796 pw.println(" disabledComponents:");
5797 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005798 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 }
5800 }
5801 if (ps.enabledComponents.size() > 0) {
5802 pw.println(" enabledComponents:");
5803 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005804 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005805 }
5806 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005807 if (ps.grantedPermissions.size() > 0) {
5808 pw.println(" grantedPermissions:");
5809 for (String s : ps.grantedPermissions) {
5810 pw.print(" "); pw.println(s);
5811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005812 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005813 if (ps.loadedPermissions.size() > 0) {
5814 pw.println(" loadedPermissions:");
5815 for (String s : ps.loadedPermissions) {
5816 pw.print(" "); pw.println(s);
5817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005818 }
5819 }
5820 }
5821 pw.println(" ");
5822 pw.println("Shared Users:");
5823 {
5824 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005825 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5826 pw.print(Integer.toHexString(System.identityHashCode(su)));
5827 pw.println("):");
5828 pw.print(" userId="); pw.print(su.userId);
5829 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 pw.println(" grantedPermissions:");
5831 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005832 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 }
5834 pw.println(" loadedPermissions:");
5835 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005836 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005837 }
5838 }
5839 }
5840 pw.println(" ");
5841 pw.println("Settings parse messages:");
5842 pw.println(mSettings.mReadMessages.toString());
5843 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005844
5845 synchronized (mProviders) {
5846 pw.println(" ");
5847 pw.println("Registered ContentProviders:");
5848 for (PackageParser.Provider p : mProviders.values()) {
5849 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5850 pw.println(p.toString());
5851 }
5852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 }
5854
5855 static final class BasePermission {
5856 final static int TYPE_NORMAL = 0;
5857 final static int TYPE_BUILTIN = 1;
5858 final static int TYPE_DYNAMIC = 2;
5859
5860 final String name;
5861 final String sourcePackage;
5862 final int type;
5863 PackageParser.Permission perm;
5864 PermissionInfo pendingInfo;
5865 int uid;
5866 int[] gids;
5867
5868 BasePermission(String _name, String _sourcePackage, int _type) {
5869 name = _name;
5870 sourcePackage = _sourcePackage;
5871 type = _type;
5872 }
5873 }
5874
5875 static class PackageSignatures {
5876 private Signature[] mSignatures;
5877
5878 PackageSignatures(Signature[] sigs) {
5879 assignSignatures(sigs);
5880 }
5881
5882 PackageSignatures() {
5883 }
5884
5885 void writeXml(XmlSerializer serializer, String tagName,
5886 ArrayList<Signature> pastSignatures) throws IOException {
5887 if (mSignatures == null) {
5888 return;
5889 }
5890 serializer.startTag(null, tagName);
5891 serializer.attribute(null, "count",
5892 Integer.toString(mSignatures.length));
5893 for (int i=0; i<mSignatures.length; i++) {
5894 serializer.startTag(null, "cert");
5895 final Signature sig = mSignatures[i];
5896 final int sigHash = sig.hashCode();
5897 final int numPast = pastSignatures.size();
5898 int j;
5899 for (j=0; j<numPast; j++) {
5900 Signature pastSig = pastSignatures.get(j);
5901 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5902 serializer.attribute(null, "index", Integer.toString(j));
5903 break;
5904 }
5905 }
5906 if (j >= numPast) {
5907 pastSignatures.add(sig);
5908 serializer.attribute(null, "index", Integer.toString(numPast));
5909 serializer.attribute(null, "key", sig.toCharsString());
5910 }
5911 serializer.endTag(null, "cert");
5912 }
5913 serializer.endTag(null, tagName);
5914 }
5915
5916 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5917 throws IOException, XmlPullParserException {
5918 String countStr = parser.getAttributeValue(null, "count");
5919 if (countStr == null) {
5920 reportSettingsProblem(Log.WARN,
5921 "Error in package manager settings: <signatures> has"
5922 + " no count at " + parser.getPositionDescription());
5923 XmlUtils.skipCurrentTag(parser);
5924 }
5925 final int count = Integer.parseInt(countStr);
5926 mSignatures = new Signature[count];
5927 int pos = 0;
5928
5929 int outerDepth = parser.getDepth();
5930 int type;
5931 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5932 && (type != XmlPullParser.END_TAG
5933 || parser.getDepth() > outerDepth)) {
5934 if (type == XmlPullParser.END_TAG
5935 || type == XmlPullParser.TEXT) {
5936 continue;
5937 }
5938
5939 String tagName = parser.getName();
5940 if (tagName.equals("cert")) {
5941 if (pos < count) {
5942 String index = parser.getAttributeValue(null, "index");
5943 if (index != null) {
5944 try {
5945 int idx = Integer.parseInt(index);
5946 String key = parser.getAttributeValue(null, "key");
5947 if (key == null) {
5948 if (idx >= 0 && idx < pastSignatures.size()) {
5949 Signature sig = pastSignatures.get(idx);
5950 if (sig != null) {
5951 mSignatures[pos] = pastSignatures.get(idx);
5952 pos++;
5953 } else {
5954 reportSettingsProblem(Log.WARN,
5955 "Error in package manager settings: <cert> "
5956 + "index " + index + " is not defined at "
5957 + parser.getPositionDescription());
5958 }
5959 } else {
5960 reportSettingsProblem(Log.WARN,
5961 "Error in package manager settings: <cert> "
5962 + "index " + index + " is out of bounds at "
5963 + parser.getPositionDescription());
5964 }
5965 } else {
5966 while (pastSignatures.size() <= idx) {
5967 pastSignatures.add(null);
5968 }
5969 Signature sig = new Signature(key);
5970 pastSignatures.set(idx, sig);
5971 mSignatures[pos] = sig;
5972 pos++;
5973 }
5974 } catch (NumberFormatException e) {
5975 reportSettingsProblem(Log.WARN,
5976 "Error in package manager settings: <cert> "
5977 + "index " + index + " is not a number at "
5978 + parser.getPositionDescription());
5979 }
5980 } else {
5981 reportSettingsProblem(Log.WARN,
5982 "Error in package manager settings: <cert> has"
5983 + " no index at " + parser.getPositionDescription());
5984 }
5985 } else {
5986 reportSettingsProblem(Log.WARN,
5987 "Error in package manager settings: too "
5988 + "many <cert> tags, expected " + count
5989 + " at " + parser.getPositionDescription());
5990 }
5991 } else {
5992 reportSettingsProblem(Log.WARN,
5993 "Unknown element under <cert>: "
5994 + parser.getName());
5995 }
5996 XmlUtils.skipCurrentTag(parser);
5997 }
5998
5999 if (pos < count) {
6000 // Should never happen -- there is an error in the written
6001 // settings -- but if it does we don't want to generate
6002 // a bad array.
6003 Signature[] newSigs = new Signature[pos];
6004 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
6005 mSignatures = newSigs;
6006 }
6007 }
6008
6009 /**
6010 * If any of the given 'sigs' is contained in the existing signatures,
6011 * then completely replace the current signatures with the ones in
6012 * 'sigs'. This is used for updating an existing package to a newly
6013 * installed version.
6014 */
6015 boolean updateSignatures(Signature[] sigs, boolean update) {
6016 if (mSignatures == null) {
6017 if (update) {
6018 assignSignatures(sigs);
6019 }
6020 return true;
6021 }
6022 if (sigs == null) {
6023 return false;
6024 }
6025
6026 for (int i=0; i<sigs.length; i++) {
6027 Signature sig = sigs[i];
6028 for (int j=0; j<mSignatures.length; j++) {
6029 if (mSignatures[j].equals(sig)) {
6030 if (update) {
6031 assignSignatures(sigs);
6032 }
6033 return true;
6034 }
6035 }
6036 }
6037 return false;
6038 }
6039
6040 /**
6041 * If any of the given 'sigs' is contained in the existing signatures,
6042 * then add in any new signatures found in 'sigs'. This is used for
6043 * including a new package into an existing shared user id.
6044 */
6045 boolean mergeSignatures(Signature[] sigs, boolean update) {
6046 if (mSignatures == null) {
6047 if (update) {
6048 assignSignatures(sigs);
6049 }
6050 return true;
6051 }
6052 if (sigs == null) {
6053 return false;
6054 }
6055
6056 Signature[] added = null;
6057 int addedCount = 0;
6058 boolean haveMatch = false;
6059 for (int i=0; i<sigs.length; i++) {
6060 Signature sig = sigs[i];
6061 boolean found = false;
6062 for (int j=0; j<mSignatures.length; j++) {
6063 if (mSignatures[j].equals(sig)) {
6064 found = true;
6065 haveMatch = true;
6066 break;
6067 }
6068 }
6069
6070 if (!found) {
6071 if (added == null) {
6072 added = new Signature[sigs.length];
6073 }
6074 added[i] = sig;
6075 addedCount++;
6076 }
6077 }
6078
6079 if (!haveMatch) {
6080 // Nothing matched -- reject the new signatures.
6081 return false;
6082 }
6083 if (added == null) {
6084 // Completely matched -- nothing else to do.
6085 return true;
6086 }
6087
6088 // Add additional signatures in.
6089 if (update) {
6090 Signature[] total = new Signature[addedCount+mSignatures.length];
6091 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6092 int j = mSignatures.length;
6093 for (int i=0; i<added.length; i++) {
6094 if (added[i] != null) {
6095 total[j] = added[i];
6096 j++;
6097 }
6098 }
6099 mSignatures = total;
6100 }
6101 return true;
6102 }
6103
6104 private void assignSignatures(Signature[] sigs) {
6105 if (sigs == null) {
6106 mSignatures = null;
6107 return;
6108 }
6109 mSignatures = new Signature[sigs.length];
6110 for (int i=0; i<sigs.length; i++) {
6111 mSignatures[i] = sigs[i];
6112 }
6113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 @Override
6116 public String toString() {
6117 StringBuffer buf = new StringBuffer(128);
6118 buf.append("PackageSignatures{");
6119 buf.append(Integer.toHexString(System.identityHashCode(this)));
6120 buf.append(" [");
6121 if (mSignatures != null) {
6122 for (int i=0; i<mSignatures.length; i++) {
6123 if (i > 0) buf.append(", ");
6124 buf.append(Integer.toHexString(
6125 System.identityHashCode(mSignatures[i])));
6126 }
6127 }
6128 buf.append("]}");
6129 return buf.toString();
6130 }
6131 }
6132
6133 static class PreferredActivity extends IntentFilter {
6134 final int mMatch;
6135 final String[] mSetPackages;
6136 final String[] mSetClasses;
6137 final String[] mSetComponents;
6138 final ComponentName mActivity;
6139 final String mShortActivity;
6140 String mParseError;
6141
6142 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6143 ComponentName activity) {
6144 super(filter);
6145 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6146 mActivity = activity;
6147 mShortActivity = activity.flattenToShortString();
6148 mParseError = null;
6149 if (set != null) {
6150 final int N = set.length;
6151 String[] myPackages = new String[N];
6152 String[] myClasses = new String[N];
6153 String[] myComponents = new String[N];
6154 for (int i=0; i<N; i++) {
6155 ComponentName cn = set[i];
6156 if (cn == null) {
6157 mSetPackages = null;
6158 mSetClasses = null;
6159 mSetComponents = null;
6160 return;
6161 }
6162 myPackages[i] = cn.getPackageName().intern();
6163 myClasses[i] = cn.getClassName().intern();
6164 myComponents[i] = cn.flattenToShortString().intern();
6165 }
6166 mSetPackages = myPackages;
6167 mSetClasses = myClasses;
6168 mSetComponents = myComponents;
6169 } else {
6170 mSetPackages = null;
6171 mSetClasses = null;
6172 mSetComponents = null;
6173 }
6174 }
6175
6176 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
6177 IOException {
6178 mShortActivity = parser.getAttributeValue(null, "name");
6179 mActivity = ComponentName.unflattenFromString(mShortActivity);
6180 if (mActivity == null) {
6181 mParseError = "Bad activity name " + mShortActivity;
6182 }
6183 String matchStr = parser.getAttributeValue(null, "match");
6184 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
6185 String setCountStr = parser.getAttributeValue(null, "set");
6186 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
6187
6188 String[] myPackages = setCount > 0 ? new String[setCount] : null;
6189 String[] myClasses = setCount > 0 ? new String[setCount] : null;
6190 String[] myComponents = setCount > 0 ? new String[setCount] : null;
6191
6192 int setPos = 0;
6193
6194 int outerDepth = parser.getDepth();
6195 int type;
6196 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6197 && (type != XmlPullParser.END_TAG
6198 || parser.getDepth() > outerDepth)) {
6199 if (type == XmlPullParser.END_TAG
6200 || type == XmlPullParser.TEXT) {
6201 continue;
6202 }
6203
6204 String tagName = parser.getName();
6205 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
6206 // + parser.getDepth() + " tag=" + tagName);
6207 if (tagName.equals("set")) {
6208 String name = parser.getAttributeValue(null, "name");
6209 if (name == null) {
6210 if (mParseError == null) {
6211 mParseError = "No name in set tag in preferred activity "
6212 + mShortActivity;
6213 }
6214 } else if (setPos >= setCount) {
6215 if (mParseError == null) {
6216 mParseError = "Too many set tags in preferred activity "
6217 + mShortActivity;
6218 }
6219 } else {
6220 ComponentName cn = ComponentName.unflattenFromString(name);
6221 if (cn == null) {
6222 if (mParseError == null) {
6223 mParseError = "Bad set name " + name + " in preferred activity "
6224 + mShortActivity;
6225 }
6226 } else {
6227 myPackages[setPos] = cn.getPackageName();
6228 myClasses[setPos] = cn.getClassName();
6229 myComponents[setPos] = name;
6230 setPos++;
6231 }
6232 }
6233 XmlUtils.skipCurrentTag(parser);
6234 } else if (tagName.equals("filter")) {
6235 //Log.i(TAG, "Starting to parse filter...");
6236 readFromXml(parser);
6237 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
6238 // + parser.getDepth() + " tag=" + parser.getName());
6239 } else {
6240 reportSettingsProblem(Log.WARN,
6241 "Unknown element under <preferred-activities>: "
6242 + parser.getName());
6243 XmlUtils.skipCurrentTag(parser);
6244 }
6245 }
6246
6247 if (setPos != setCount) {
6248 if (mParseError == null) {
6249 mParseError = "Not enough set tags (expected " + setCount
6250 + " but found " + setPos + ") in " + mShortActivity;
6251 }
6252 }
6253
6254 mSetPackages = myPackages;
6255 mSetClasses = myClasses;
6256 mSetComponents = myComponents;
6257 }
6258
6259 public void writeToXml(XmlSerializer serializer) throws IOException {
6260 final int NS = mSetClasses != null ? mSetClasses.length : 0;
6261 serializer.attribute(null, "name", mShortActivity);
6262 serializer.attribute(null, "match", Integer.toHexString(mMatch));
6263 serializer.attribute(null, "set", Integer.toString(NS));
6264 for (int s=0; s<NS; s++) {
6265 serializer.startTag(null, "set");
6266 serializer.attribute(null, "name", mSetComponents[s]);
6267 serializer.endTag(null, "set");
6268 }
6269 serializer.startTag(null, "filter");
6270 super.writeToXml(serializer);
6271 serializer.endTag(null, "filter");
6272 }
6273
6274 boolean sameSet(List<ResolveInfo> query, int priority) {
6275 if (mSetPackages == null) return false;
6276 final int NQ = query.size();
6277 final int NS = mSetPackages.length;
6278 int numMatch = 0;
6279 for (int i=0; i<NQ; i++) {
6280 ResolveInfo ri = query.get(i);
6281 if (ri.priority != priority) continue;
6282 ActivityInfo ai = ri.activityInfo;
6283 boolean good = false;
6284 for (int j=0; j<NS; j++) {
6285 if (mSetPackages[j].equals(ai.packageName)
6286 && mSetClasses[j].equals(ai.name)) {
6287 numMatch++;
6288 good = true;
6289 break;
6290 }
6291 }
6292 if (!good) return false;
6293 }
6294 return numMatch == NS;
6295 }
6296 }
6297
6298 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006299 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006301 HashSet<String> grantedPermissions = new HashSet<String>();
6302 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006304 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08006307 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
6308 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
6309 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006310 }
6311 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 /**
6314 * Settings base class for pending and resolved classes.
6315 */
6316 static class PackageSettingBase extends GrantedPermissions {
6317 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006318 File codePath;
6319 String codePathString;
6320 File resourcePath;
6321 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 private long timeStamp;
6323 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006324 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325
6326 PackageSignatures signatures = new PackageSignatures();
6327
6328 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006330 /* Explicitly disabled components */
6331 HashSet<String> disabledComponents = new HashSet<String>(0);
6332 /* Explicitly enabled components */
6333 HashSet<String> enabledComponents = new HashSet<String>(0);
6334 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6335 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006336
Jacek Surazski65e13172009-04-28 15:26:38 +02006337 /* package name of the app that installed this package */
6338 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339
6340 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006341 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 super(pkgFlags);
6343 this.name = name;
6344 this.codePath = codePath;
6345 this.codePathString = codePath.toString();
6346 this.resourcePath = resourcePath;
6347 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006348 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 }
6350
Jacek Surazski65e13172009-04-28 15:26:38 +02006351 public void setInstallerPackageName(String packageName) {
6352 installerPackageName = packageName;
6353 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006354
Jacek Surazski65e13172009-04-28 15:26:38 +02006355 String getInstallerPackageName() {
6356 return installerPackageName;
6357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 public void setInstallStatus(int newStatus) {
6360 installStatus = newStatus;
6361 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 public int getInstallStatus() {
6364 return installStatus;
6365 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006367 public void setTimeStamp(long newStamp) {
6368 if (newStamp != timeStamp) {
6369 timeStamp = newStamp;
6370 timeStampString = Long.toString(newStamp);
6371 }
6372 }
6373
6374 public void setTimeStamp(long newStamp, String newStampStr) {
6375 timeStamp = newStamp;
6376 timeStampString = newStampStr;
6377 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 public long getTimeStamp() {
6380 return timeStamp;
6381 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 public String getTimeStampStr() {
6384 return timeStampString;
6385 }
6386
6387 public void copyFrom(PackageSettingBase base) {
6388 grantedPermissions = base.grantedPermissions;
6389 gids = base.gids;
6390 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006392 timeStamp = base.timeStamp;
6393 timeStampString = base.timeStampString;
6394 signatures = base.signatures;
6395 permissionsFixed = base.permissionsFixed;
6396 disabledComponents = base.disabledComponents;
6397 enabledComponents = base.enabledComponents;
6398 enabled = base.enabled;
6399 installStatus = base.installStatus;
6400 }
6401
6402 void enableComponentLP(String componentClassName) {
6403 disabledComponents.remove(componentClassName);
6404 enabledComponents.add(componentClassName);
6405 }
6406
6407 void disableComponentLP(String componentClassName) {
6408 enabledComponents.remove(componentClassName);
6409 disabledComponents.add(componentClassName);
6410 }
6411
6412 void restoreComponentLP(String componentClassName) {
6413 enabledComponents.remove(componentClassName);
6414 disabledComponents.remove(componentClassName);
6415 }
6416
6417 int currentEnabledStateLP(String componentName) {
6418 if (enabledComponents.contains(componentName)) {
6419 return COMPONENT_ENABLED_STATE_ENABLED;
6420 } else if (disabledComponents.contains(componentName)) {
6421 return COMPONENT_ENABLED_STATE_DISABLED;
6422 } else {
6423 return COMPONENT_ENABLED_STATE_DEFAULT;
6424 }
6425 }
6426 }
6427
6428 /**
6429 * Settings data for a particular package we know about.
6430 */
6431 static final class PackageSetting extends PackageSettingBase {
6432 int userId;
6433 PackageParser.Package pkg;
6434 SharedUserSetting sharedUser;
6435
6436 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006437 int pVersionCode, int pkgFlags) {
6438 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006439 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006441 @Override
6442 public String toString() {
6443 return "PackageSetting{"
6444 + Integer.toHexString(System.identityHashCode(this))
6445 + " " + name + "/" + userId + "}";
6446 }
6447 }
6448
6449 /**
6450 * Settings data for a particular shared user ID we know about.
6451 */
6452 static final class SharedUserSetting extends GrantedPermissions {
6453 final String name;
6454 int userId;
6455 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6456 final PackageSignatures signatures = new PackageSignatures();
6457
6458 SharedUserSetting(String _name, int _pkgFlags) {
6459 super(_pkgFlags);
6460 name = _name;
6461 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006463 @Override
6464 public String toString() {
6465 return "SharedUserSetting{"
6466 + Integer.toHexString(System.identityHashCode(this))
6467 + " " + name + "/" + userId + "}";
6468 }
6469 }
6470
6471 /**
6472 * Holds information about dynamic settings.
6473 */
6474 private static final class Settings {
6475 private final File mSettingsFilename;
6476 private final File mBackupSettingsFilename;
6477 private final HashMap<String, PackageSetting> mPackages =
6478 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006479 // List of replaced system applications
6480 final HashMap<String, PackageSetting> mDisabledSysPackages =
6481 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006483 // The user's preferred activities associated with particular intent
6484 // filters.
6485 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6486 new IntentResolver<PreferredActivity, PreferredActivity>() {
6487 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006488 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006490 out.print(prefix); out.print(
6491 Integer.toHexString(System.identityHashCode(filter)));
6492 out.print(' ');
6493 out.print(filter.mActivity.flattenToShortString());
6494 out.print(" match=0x");
6495 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006497 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006498 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006499 out.print(prefix); out.print(" ");
6500 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 }
6502 }
6503 }
6504 };
6505 private final HashMap<String, SharedUserSetting> mSharedUsers =
6506 new HashMap<String, SharedUserSetting>();
6507 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6508 private final SparseArray<Object> mOtherUserIds =
6509 new SparseArray<Object>();
6510
6511 // For reading/writing settings file.
6512 private final ArrayList<Signature> mPastSignatures =
6513 new ArrayList<Signature>();
6514
6515 // Mapping from permission names to info about them.
6516 final HashMap<String, BasePermission> mPermissions =
6517 new HashMap<String, BasePermission>();
6518
6519 // Mapping from permission tree names to info about them.
6520 final HashMap<String, BasePermission> mPermissionTrees =
6521 new HashMap<String, BasePermission>();
6522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 private final StringBuilder mReadMessages = new StringBuilder();
6524
6525 private static final class PendingPackage extends PackageSettingBase {
6526 final int sharedId;
6527
6528 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006529 int sharedId, int pVersionCode, int pkgFlags) {
6530 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006531 this.sharedId = sharedId;
6532 }
6533 }
6534 private final ArrayList<PendingPackage> mPendingPackages
6535 = new ArrayList<PendingPackage>();
6536
6537 Settings() {
6538 File dataDir = Environment.getDataDirectory();
6539 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006540 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6541 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006542 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006543 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 FileUtils.setPermissions(systemDir.toString(),
6545 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6546 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6547 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006548 FileUtils.setPermissions(systemSecureDir.toString(),
6549 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6550 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6551 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006552 mSettingsFilename = new File(systemDir, "packages.xml");
6553 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6554 }
6555
6556 PackageSetting getPackageLP(PackageParser.Package pkg,
6557 SharedUserSetting sharedUser, File codePath, File resourcePath,
6558 int pkgFlags, boolean create, boolean add) {
6559 final String name = pkg.packageName;
6560 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006561 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 return p;
6563 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006564
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006565 PackageSetting peekPackageLP(String name) {
6566 return mPackages.get(name);
6567 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 PackageSetting p = mPackages.get(name);
6569 if (p != null && p.codePath.getPath().equals(codePath)) {
6570 return p;
6571 }
6572 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006573 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 void setInstallStatus(String pkgName, int status) {
6577 PackageSetting p = mPackages.get(pkgName);
6578 if(p != null) {
6579 if(p.getInstallStatus() != status) {
6580 p.setInstallStatus(status);
6581 }
6582 }
6583 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006584
Jacek Surazski65e13172009-04-28 15:26:38 +02006585 void setInstallerPackageName(String pkgName,
6586 String installerPkgName) {
6587 PackageSetting p = mPackages.get(pkgName);
6588 if(p != null) {
6589 p.setInstallerPackageName(installerPkgName);
6590 }
6591 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006592
Jacek Surazski65e13172009-04-28 15:26:38 +02006593 String getInstallerPackageName(String pkgName) {
6594 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006595 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006596 }
6597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006598 int getInstallStatus(String pkgName) {
6599 PackageSetting p = mPackages.get(pkgName);
6600 if(p != null) {
6601 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006603 return -1;
6604 }
6605
6606 SharedUserSetting getSharedUserLP(String name,
6607 int pkgFlags, boolean create) {
6608 SharedUserSetting s = mSharedUsers.get(name);
6609 if (s == null) {
6610 if (!create) {
6611 return null;
6612 }
6613 s = new SharedUserSetting(name, pkgFlags);
6614 if (MULTIPLE_APPLICATION_UIDS) {
6615 s.userId = newUserIdLP(s);
6616 } else {
6617 s.userId = FIRST_APPLICATION_UID;
6618 }
6619 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6620 // < 0 means we couldn't assign a userid; fall out and return
6621 // s, which is currently null
6622 if (s.userId >= 0) {
6623 mSharedUsers.put(name, s);
6624 }
6625 }
6626
6627 return s;
6628 }
6629
6630 int disableSystemPackageLP(String name) {
6631 PackageSetting p = mPackages.get(name);
6632 if(p == null) {
6633 Log.w(TAG, "Package:"+name+" is not an installed package");
6634 return -1;
6635 }
6636 PackageSetting dp = mDisabledSysPackages.get(name);
6637 // always make sure the system package code and resource paths dont change
6638 if(dp == null) {
6639 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6640 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6641 }
6642 mDisabledSysPackages.put(name, p);
6643 }
6644 return removePackageLP(name);
6645 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006647 PackageSetting enableSystemPackageLP(String name) {
6648 PackageSetting p = mDisabledSysPackages.get(name);
6649 if(p == null) {
6650 Log.w(TAG, "Package:"+name+" is not disabled");
6651 return null;
6652 }
6653 // Reset flag in ApplicationInfo object
6654 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6655 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6656 }
6657 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006658 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 mDisabledSysPackages.remove(name);
6660 return ret;
6661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006664 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 PackageSetting p = mPackages.get(name);
6666 if (p != null) {
6667 if (p.userId == uid) {
6668 return p;
6669 }
6670 reportSettingsProblem(Log.ERROR,
6671 "Adding duplicate package, keeping first: " + name);
6672 return null;
6673 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006674 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 p.userId = uid;
6676 if (addUserIdLP(uid, p, name)) {
6677 mPackages.put(name, p);
6678 return p;
6679 }
6680 return null;
6681 }
6682
6683 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6684 SharedUserSetting s = mSharedUsers.get(name);
6685 if (s != null) {
6686 if (s.userId == uid) {
6687 return s;
6688 }
6689 reportSettingsProblem(Log.ERROR,
6690 "Adding duplicate shared user, keeping first: " + name);
6691 return null;
6692 }
6693 s = new SharedUserSetting(name, pkgFlags);
6694 s.userId = uid;
6695 if (addUserIdLP(uid, s, name)) {
6696 mSharedUsers.put(name, s);
6697 return s;
6698 }
6699 return null;
6700 }
6701
6702 private PackageSetting getPackageLP(String name,
6703 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006704 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 PackageSetting p = mPackages.get(name);
6706 if (p != null) {
6707 if (!p.codePath.equals(codePath)) {
6708 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006709 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006710 // This is an updated system app with versions in both system
6711 // and data partition. Just let the most recent version
6712 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006713 Log.w(TAG, "Trying to update system app code path from " +
6714 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006715 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006716 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006717 reportSettingsProblem(Log.WARN,
6718 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006719 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006720 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006721 }
6722 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006723 reportSettingsProblem(Log.WARN,
6724 "Package " + name + " shared user changed from "
6725 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6726 + " to "
6727 + (sharedUser != null ? sharedUser.name : "<nothing>")
6728 + "; replacing with new");
6729 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006730 } else {
6731 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6732 // If what we are scanning is a system package, then
6733 // make it so, regardless of whether it was previously
6734 // installed only in the data partition.
6735 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 }
6738 }
6739 if (p == null) {
6740 // Create a new PackageSettings entry. this can end up here because
6741 // of code path mismatch or user id mismatch of an updated system partition
6742 if (!create) {
6743 return null;
6744 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006745 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006747 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006748 if (sharedUser != null) {
6749 p.userId = sharedUser.userId;
6750 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006751 // Clone the setting here for disabled system packages
6752 PackageSetting dis = mDisabledSysPackages.get(name);
6753 if (dis != null) {
6754 // For disabled packages a new setting is created
6755 // from the existing user id. This still has to be
6756 // added to list of user id's
6757 // Copy signatures from previous setting
6758 if (dis.signatures.mSignatures != null) {
6759 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6760 }
6761 p.userId = dis.userId;
6762 // Clone permissions
6763 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6764 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6765 // Clone component info
6766 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6767 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6768 // Add new setting to list of user ids
6769 addUserIdLP(p.userId, p, name);
6770 } else {
6771 // Assign new user id
6772 p.userId = newUserIdLP(p);
6773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 } else {
6775 p.userId = FIRST_APPLICATION_UID;
6776 }
6777 if (p.userId < 0) {
6778 reportSettingsProblem(Log.WARN,
6779 "Package " + name + " could not be assigned a valid uid");
6780 return null;
6781 }
6782 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006783 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006785 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006786 }
6787 }
6788 return p;
6789 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006790
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006791 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006792 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006793 String codePath = pkg.applicationInfo.sourceDir;
6794 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006795 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006796 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006797 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006798 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006799 p.codePath = new File(codePath);
6800 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006801 }
6802 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006803 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006804 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006805 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006806 p.resourcePath = new File(resourcePath);
6807 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006808 }
6809 // Update version code if needed
6810 if (pkg.mVersionCode != p.versionCode) {
6811 p.versionCode = pkg.mVersionCode;
6812 }
6813 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6814 }
6815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 // Utility method that adds a PackageSetting to mPackages and
6817 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006818 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006819 SharedUserSetting sharedUser) {
6820 mPackages.put(name, p);
6821 if (sharedUser != null) {
6822 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6823 reportSettingsProblem(Log.ERROR,
6824 "Package " + p.name + " was user "
6825 + p.sharedUser + " but is now " + sharedUser
6826 + "; I am not changing its files so it will probably fail!");
6827 p.sharedUser.packages.remove(p);
6828 } else if (p.userId != sharedUser.userId) {
6829 reportSettingsProblem(Log.ERROR,
6830 "Package " + p.name + " was user id " + p.userId
6831 + " but is now user " + sharedUser
6832 + " with id " + sharedUser.userId
6833 + "; I am not changing its files so it will probably fail!");
6834 }
6835
6836 sharedUser.packages.add(p);
6837 p.sharedUser = sharedUser;
6838 p.userId = sharedUser.userId;
6839 }
6840 }
6841
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006842 /*
6843 * Update the shared user setting when a package using
6844 * specifying the shared user id is removed. The gids
6845 * associated with each permission of the deleted package
6846 * are removed from the shared user's gid list only if its
6847 * not in use by other permissions of packages in the
6848 * shared user setting.
6849 */
6850 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006851 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6852 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6853 return;
6854 }
6855 // No sharedUserId
6856 if (deletedPs.sharedUser == null) {
6857 return;
6858 }
6859 SharedUserSetting sus = deletedPs.sharedUser;
6860 // Update permissions
6861 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6862 boolean used = false;
6863 if (!sus.grantedPermissions.contains (eachPerm)) {
6864 continue;
6865 }
6866 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006867 if (pkg.pkg != null &&
6868 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6869 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 used = true;
6871 break;
6872 }
6873 }
6874 if (!used) {
6875 // can safely delete this permission from list
6876 sus.grantedPermissions.remove(eachPerm);
6877 sus.loadedPermissions.remove(eachPerm);
6878 }
6879 }
6880 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006881 int newGids[] = globalGids;
6882 for (String eachPerm : sus.grantedPermissions) {
6883 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006884 if (bp != null) {
6885 newGids = appendInts(newGids, bp.gids);
6886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006887 }
6888 sus.gids = newGids;
6889 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 private int removePackageLP(String name) {
6892 PackageSetting p = mPackages.get(name);
6893 if (p != null) {
6894 mPackages.remove(name);
6895 if (p.sharedUser != null) {
6896 p.sharedUser.packages.remove(p);
6897 if (p.sharedUser.packages.size() == 0) {
6898 mSharedUsers.remove(p.sharedUser.name);
6899 removeUserIdLP(p.sharedUser.userId);
6900 return p.sharedUser.userId;
6901 }
6902 } else {
6903 removeUserIdLP(p.userId);
6904 return p.userId;
6905 }
6906 }
6907 return -1;
6908 }
6909
6910 private boolean addUserIdLP(int uid, Object obj, Object name) {
6911 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6912 return false;
6913 }
6914
6915 if (uid >= FIRST_APPLICATION_UID) {
6916 int N = mUserIds.size();
6917 final int index = uid - FIRST_APPLICATION_UID;
6918 while (index >= N) {
6919 mUserIds.add(null);
6920 N++;
6921 }
6922 if (mUserIds.get(index) != null) {
6923 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006924 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006925 + " name=" + name);
6926 return false;
6927 }
6928 mUserIds.set(index, obj);
6929 } else {
6930 if (mOtherUserIds.get(uid) != null) {
6931 reportSettingsProblem(Log.ERROR,
6932 "Adding duplicate shared id: " + uid
6933 + " name=" + name);
6934 return false;
6935 }
6936 mOtherUserIds.put(uid, obj);
6937 }
6938 return true;
6939 }
6940
6941 public Object getUserIdLP(int uid) {
6942 if (uid >= FIRST_APPLICATION_UID) {
6943 int N = mUserIds.size();
6944 final int index = uid - FIRST_APPLICATION_UID;
6945 return index < N ? mUserIds.get(index) : null;
6946 } else {
6947 return mOtherUserIds.get(uid);
6948 }
6949 }
6950
6951 private void removeUserIdLP(int uid) {
6952 if (uid >= FIRST_APPLICATION_UID) {
6953 int N = mUserIds.size();
6954 final int index = uid - FIRST_APPLICATION_UID;
6955 if (index < N) mUserIds.set(index, null);
6956 } else {
6957 mOtherUserIds.remove(uid);
6958 }
6959 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006961 void writeLP() {
6962 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6963
6964 // Keep the old settings around until we know the new ones have
6965 // been successfully written.
6966 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006967 // Presence of backup settings file indicates that we failed
6968 // to persist settings earlier. So preserve the older
6969 // backup for future reference since the current settings
6970 // might have been corrupted.
6971 if (!mBackupSettingsFilename.exists()) {
6972 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6973 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6974 return;
6975 }
6976 } else {
6977 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006979 }
6980
6981 mPastSignatures.clear();
6982
6983 try {
6984 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6985
6986 //XmlSerializer serializer = XmlUtils.serializerInstance();
6987 XmlSerializer serializer = new FastXmlSerializer();
6988 serializer.setOutput(str, "utf-8");
6989 serializer.startDocument(null, true);
6990 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6991
6992 serializer.startTag(null, "packages");
6993
6994 serializer.startTag(null, "permission-trees");
6995 for (BasePermission bp : mPermissionTrees.values()) {
6996 writePermission(serializer, bp);
6997 }
6998 serializer.endTag(null, "permission-trees");
6999
7000 serializer.startTag(null, "permissions");
7001 for (BasePermission bp : mPermissions.values()) {
7002 writePermission(serializer, bp);
7003 }
7004 serializer.endTag(null, "permissions");
7005
7006 for (PackageSetting pkg : mPackages.values()) {
7007 writePackage(serializer, pkg);
7008 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007010 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7011 writeDisabledSysPackage(serializer, pkg);
7012 }
7013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 serializer.startTag(null, "preferred-activities");
7015 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7016 serializer.startTag(null, "item");
7017 pa.writeToXml(serializer);
7018 serializer.endTag(null, "item");
7019 }
7020 serializer.endTag(null, "preferred-activities");
7021
7022 for (SharedUserSetting usr : mSharedUsers.values()) {
7023 serializer.startTag(null, "shared-user");
7024 serializer.attribute(null, "name", usr.name);
7025 serializer.attribute(null, "userId",
7026 Integer.toString(usr.userId));
7027 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7028 serializer.startTag(null, "perms");
7029 for (String name : usr.grantedPermissions) {
7030 serializer.startTag(null, "item");
7031 serializer.attribute(null, "name", name);
7032 serializer.endTag(null, "item");
7033 }
7034 serializer.endTag(null, "perms");
7035 serializer.endTag(null, "shared-user");
7036 }
7037
7038 serializer.endTag(null, "packages");
7039
7040 serializer.endDocument();
7041
7042 str.flush();
7043 str.close();
7044
7045 // New settings successfully written, old ones are no longer
7046 // needed.
7047 mBackupSettingsFilename.delete();
7048 FileUtils.setPermissions(mSettingsFilename.toString(),
7049 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7050 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7051 |FileUtils.S_IROTH,
7052 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007053 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054
7055 } catch(XmlPullParserException e) {
7056 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 -08007057 } catch(java.io.IOException e) {
7058 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 -08007059 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007060 // Clean up partially written file
7061 if (mSettingsFilename.exists()) {
7062 if (!mSettingsFilename.delete()) {
7063 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
7064 }
7065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007066 //Debug.stopMethodTracing();
7067 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007068
7069 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007070 throws java.io.IOException {
7071 serializer.startTag(null, "updated-package");
7072 serializer.attribute(null, "name", pkg.name);
7073 serializer.attribute(null, "codePath", pkg.codePathString);
7074 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007075 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007076 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7077 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7078 }
7079 if (pkg.sharedUser == null) {
7080 serializer.attribute(null, "userId",
7081 Integer.toString(pkg.userId));
7082 } else {
7083 serializer.attribute(null, "sharedUserId",
7084 Integer.toString(pkg.userId));
7085 }
7086 serializer.startTag(null, "perms");
7087 if (pkg.sharedUser == null) {
7088 // If this is a shared user, the permissions will
7089 // be written there. We still need to write an
7090 // empty permissions list so permissionsFixed will
7091 // be set.
7092 for (final String name : pkg.grantedPermissions) {
7093 BasePermission bp = mPermissions.get(name);
7094 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
7095 // We only need to write signature or system permissions but this wont
7096 // match the semantics of grantedPermissions. So write all permissions.
7097 serializer.startTag(null, "item");
7098 serializer.attribute(null, "name", name);
7099 serializer.endTag(null, "item");
7100 }
7101 }
7102 }
7103 serializer.endTag(null, "perms");
7104 serializer.endTag(null, "updated-package");
7105 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007106
7107 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007108 throws java.io.IOException {
7109 serializer.startTag(null, "package");
7110 serializer.attribute(null, "name", pkg.name);
7111 serializer.attribute(null, "codePath", pkg.codePathString);
7112 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7113 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7114 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007115 serializer.attribute(null, "flags",
7116 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007117 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007118 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007119 if (pkg.sharedUser == null) {
7120 serializer.attribute(null, "userId",
7121 Integer.toString(pkg.userId));
7122 } else {
7123 serializer.attribute(null, "sharedUserId",
7124 Integer.toString(pkg.userId));
7125 }
7126 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
7127 serializer.attribute(null, "enabled",
7128 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
7129 ? "true" : "false");
7130 }
7131 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
7132 serializer.attribute(null, "installStatus", "false");
7133 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007134 if (pkg.installerPackageName != null) {
7135 serializer.attribute(null, "installer", pkg.installerPackageName);
7136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007137 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
7138 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
7139 serializer.startTag(null, "perms");
7140 if (pkg.sharedUser == null) {
7141 // If this is a shared user, the permissions will
7142 // be written there. We still need to write an
7143 // empty permissions list so permissionsFixed will
7144 // be set.
7145 for (final String name : pkg.grantedPermissions) {
7146 serializer.startTag(null, "item");
7147 serializer.attribute(null, "name", name);
7148 serializer.endTag(null, "item");
7149 }
7150 }
7151 serializer.endTag(null, "perms");
7152 }
7153 if (pkg.disabledComponents.size() > 0) {
7154 serializer.startTag(null, "disabled-components");
7155 for (final String name : pkg.disabledComponents) {
7156 serializer.startTag(null, "item");
7157 serializer.attribute(null, "name", name);
7158 serializer.endTag(null, "item");
7159 }
7160 serializer.endTag(null, "disabled-components");
7161 }
7162 if (pkg.enabledComponents.size() > 0) {
7163 serializer.startTag(null, "enabled-components");
7164 for (final String name : pkg.enabledComponents) {
7165 serializer.startTag(null, "item");
7166 serializer.attribute(null, "name", name);
7167 serializer.endTag(null, "item");
7168 }
7169 serializer.endTag(null, "enabled-components");
7170 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007172 serializer.endTag(null, "package");
7173 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 void writePermission(XmlSerializer serializer, BasePermission bp)
7176 throws XmlPullParserException, java.io.IOException {
7177 if (bp.type != BasePermission.TYPE_BUILTIN
7178 && bp.sourcePackage != null) {
7179 serializer.startTag(null, "item");
7180 serializer.attribute(null, "name", bp.name);
7181 serializer.attribute(null, "package", bp.sourcePackage);
7182 if (DEBUG_SETTINGS) Log.v(TAG,
7183 "Writing perm: name=" + bp.name + " type=" + bp.type);
7184 if (bp.type == BasePermission.TYPE_DYNAMIC) {
7185 PermissionInfo pi = bp.perm != null ? bp.perm.info
7186 : bp.pendingInfo;
7187 if (pi != null) {
7188 serializer.attribute(null, "type", "dynamic");
7189 if (pi.icon != 0) {
7190 serializer.attribute(null, "icon",
7191 Integer.toString(pi.icon));
7192 }
7193 if (pi.nonLocalizedLabel != null) {
7194 serializer.attribute(null, "label",
7195 pi.nonLocalizedLabel.toString());
7196 }
7197 if (pi.protectionLevel !=
7198 PermissionInfo.PROTECTION_NORMAL) {
7199 serializer.attribute(null, "protection",
7200 Integer.toString(pi.protectionLevel));
7201 }
7202 }
7203 }
7204 serializer.endTag(null, "item");
7205 }
7206 }
7207
7208 String getReadMessagesLP() {
7209 return mReadMessages.toString();
7210 }
7211
Oscar Montemayora8529f62009-11-18 10:14:20 -08007212 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
7214 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007215 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007216 while(its.hasNext()) {
7217 String key = its.next();
7218 PackageSetting ps = mPackages.get(key);
7219 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08007220 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 }
7222 }
7223 return ret;
7224 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 boolean readLP() {
7227 FileInputStream str = null;
7228 if (mBackupSettingsFilename.exists()) {
7229 try {
7230 str = new FileInputStream(mBackupSettingsFilename);
7231 mReadMessages.append("Reading from backup settings file\n");
7232 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007233 if (mSettingsFilename.exists()) {
7234 // If both the backup and settings file exist, we
7235 // ignore the settings since it might have been
7236 // corrupted.
7237 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
7238 mSettingsFilename.delete();
7239 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007240 } catch (java.io.IOException e) {
7241 // We'll try for the normal settings file.
7242 }
7243 }
7244
7245 mPastSignatures.clear();
7246
7247 try {
7248 if (str == null) {
7249 if (!mSettingsFilename.exists()) {
7250 mReadMessages.append("No settings file found\n");
7251 Log.i(TAG, "No current settings file!");
7252 return false;
7253 }
7254 str = new FileInputStream(mSettingsFilename);
7255 }
7256 XmlPullParser parser = Xml.newPullParser();
7257 parser.setInput(str, null);
7258
7259 int type;
7260 while ((type=parser.next()) != XmlPullParser.START_TAG
7261 && type != XmlPullParser.END_DOCUMENT) {
7262 ;
7263 }
7264
7265 if (type != XmlPullParser.START_TAG) {
7266 mReadMessages.append("No start tag found in settings file\n");
7267 Log.e(TAG, "No start tag found in package manager settings");
7268 return false;
7269 }
7270
7271 int outerDepth = parser.getDepth();
7272 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7273 && (type != XmlPullParser.END_TAG
7274 || parser.getDepth() > outerDepth)) {
7275 if (type == XmlPullParser.END_TAG
7276 || type == XmlPullParser.TEXT) {
7277 continue;
7278 }
7279
7280 String tagName = parser.getName();
7281 if (tagName.equals("package")) {
7282 readPackageLP(parser);
7283 } else if (tagName.equals("permissions")) {
7284 readPermissionsLP(mPermissions, parser);
7285 } else if (tagName.equals("permission-trees")) {
7286 readPermissionsLP(mPermissionTrees, parser);
7287 } else if (tagName.equals("shared-user")) {
7288 readSharedUserLP(parser);
7289 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007290 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 } else if (tagName.equals("preferred-activities")) {
7292 readPreferredActivitiesLP(parser);
7293 } else if(tagName.equals("updated-package")) {
7294 readDisabledSysPackageLP(parser);
7295 } else {
7296 Log.w(TAG, "Unknown element under <packages>: "
7297 + parser.getName());
7298 XmlUtils.skipCurrentTag(parser);
7299 }
7300 }
7301
7302 str.close();
7303
7304 } catch(XmlPullParserException e) {
7305 mReadMessages.append("Error reading: " + e.toString());
7306 Log.e(TAG, "Error reading package manager settings", e);
7307
7308 } catch(java.io.IOException e) {
7309 mReadMessages.append("Error reading: " + e.toString());
7310 Log.e(TAG, "Error reading package manager settings", e);
7311
7312 }
7313
7314 int N = mPendingPackages.size();
7315 for (int i=0; i<N; i++) {
7316 final PendingPackage pp = mPendingPackages.get(i);
7317 Object idObj = getUserIdLP(pp.sharedId);
7318 if (idObj != null && idObj instanceof SharedUserSetting) {
7319 PackageSetting p = getPackageLP(pp.name,
7320 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007321 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007322 if (p == null) {
7323 Log.w(TAG, "Unable to create application package for "
7324 + pp.name);
7325 continue;
7326 }
7327 p.copyFrom(pp);
7328 } else if (idObj != null) {
7329 String msg = "Bad package setting: package " + pp.name
7330 + " has shared uid " + pp.sharedId
7331 + " that is not a shared uid\n";
7332 mReadMessages.append(msg);
7333 Log.e(TAG, msg);
7334 } else {
7335 String msg = "Bad package setting: package " + pp.name
7336 + " has shared uid " + pp.sharedId
7337 + " that is not defined\n";
7338 mReadMessages.append(msg);
7339 Log.e(TAG, msg);
7340 }
7341 }
7342 mPendingPackages.clear();
7343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 mReadMessages.append("Read completed successfully: "
7345 + mPackages.size() + " packages, "
7346 + mSharedUsers.size() + " shared uids\n");
7347
7348 return true;
7349 }
7350
7351 private int readInt(XmlPullParser parser, String ns, String name,
7352 int defValue) {
7353 String v = parser.getAttributeValue(ns, name);
7354 try {
7355 if (v == null) {
7356 return defValue;
7357 }
7358 return Integer.parseInt(v);
7359 } catch (NumberFormatException e) {
7360 reportSettingsProblem(Log.WARN,
7361 "Error in package manager settings: attribute " +
7362 name + " has bad integer value " + v + " at "
7363 + parser.getPositionDescription());
7364 }
7365 return defValue;
7366 }
7367
7368 private void readPermissionsLP(HashMap<String, BasePermission> out,
7369 XmlPullParser parser)
7370 throws IOException, XmlPullParserException {
7371 int outerDepth = parser.getDepth();
7372 int type;
7373 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7374 && (type != XmlPullParser.END_TAG
7375 || parser.getDepth() > outerDepth)) {
7376 if (type == XmlPullParser.END_TAG
7377 || type == XmlPullParser.TEXT) {
7378 continue;
7379 }
7380
7381 String tagName = parser.getName();
7382 if (tagName.equals("item")) {
7383 String name = parser.getAttributeValue(null, "name");
7384 String sourcePackage = parser.getAttributeValue(null, "package");
7385 String ptype = parser.getAttributeValue(null, "type");
7386 if (name != null && sourcePackage != null) {
7387 boolean dynamic = "dynamic".equals(ptype);
7388 BasePermission bp = new BasePermission(name, sourcePackage,
7389 dynamic
7390 ? BasePermission.TYPE_DYNAMIC
7391 : BasePermission.TYPE_NORMAL);
7392 if (dynamic) {
7393 PermissionInfo pi = new PermissionInfo();
7394 pi.packageName = sourcePackage.intern();
7395 pi.name = name.intern();
7396 pi.icon = readInt(parser, null, "icon", 0);
7397 pi.nonLocalizedLabel = parser.getAttributeValue(
7398 null, "label");
7399 pi.protectionLevel = readInt(parser, null, "protection",
7400 PermissionInfo.PROTECTION_NORMAL);
7401 bp.pendingInfo = pi;
7402 }
7403 out.put(bp.name, bp);
7404 } else {
7405 reportSettingsProblem(Log.WARN,
7406 "Error in package manager settings: permissions has"
7407 + " no name at " + parser.getPositionDescription());
7408 }
7409 } else {
7410 reportSettingsProblem(Log.WARN,
7411 "Unknown element reading permissions: "
7412 + parser.getName() + " at "
7413 + parser.getPositionDescription());
7414 }
7415 XmlUtils.skipCurrentTag(parser);
7416 }
7417 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007419 private void readDisabledSysPackageLP(XmlPullParser parser)
7420 throws XmlPullParserException, IOException {
7421 String name = parser.getAttributeValue(null, "name");
7422 String codePathStr = parser.getAttributeValue(null, "codePath");
7423 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
7424 if(resourcePathStr == null) {
7425 resourcePathStr = codePathStr;
7426 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007427 String version = parser.getAttributeValue(null, "version");
7428 int versionCode = 0;
7429 if (version != null) {
7430 try {
7431 versionCode = Integer.parseInt(version);
7432 } catch (NumberFormatException e) {
7433 }
7434 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007436 int pkgFlags = 0;
7437 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007438 PackageSetting ps = new PackageSetting(name,
7439 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007440 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 String timeStampStr = parser.getAttributeValue(null, "ts");
7442 if (timeStampStr != null) {
7443 try {
7444 long timeStamp = Long.parseLong(timeStampStr);
7445 ps.setTimeStamp(timeStamp, timeStampStr);
7446 } catch (NumberFormatException e) {
7447 }
7448 }
7449 String idStr = parser.getAttributeValue(null, "userId");
7450 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7451 if(ps.userId <= 0) {
7452 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7453 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7454 }
7455 int outerDepth = parser.getDepth();
7456 int type;
7457 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7458 && (type != XmlPullParser.END_TAG
7459 || parser.getDepth() > outerDepth)) {
7460 if (type == XmlPullParser.END_TAG
7461 || type == XmlPullParser.TEXT) {
7462 continue;
7463 }
7464
7465 String tagName = parser.getName();
7466 if (tagName.equals("perms")) {
7467 readGrantedPermissionsLP(parser,
7468 ps.grantedPermissions);
7469 } else {
7470 reportSettingsProblem(Log.WARN,
7471 "Unknown element under <updated-package>: "
7472 + parser.getName());
7473 XmlUtils.skipCurrentTag(parser);
7474 }
7475 }
7476 mDisabledSysPackages.put(name, ps);
7477 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 private void readPackageLP(XmlPullParser parser)
7480 throws XmlPullParserException, IOException {
7481 String name = null;
7482 String idStr = null;
7483 String sharedIdStr = null;
7484 String codePathStr = null;
7485 String resourcePathStr = null;
7486 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007487 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007488 int pkgFlags = 0;
7489 String timeStampStr;
7490 long timeStamp = 0;
7491 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007492 String version = null;
7493 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 try {
7495 name = parser.getAttributeValue(null, "name");
7496 idStr = parser.getAttributeValue(null, "userId");
7497 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7498 codePathStr = parser.getAttributeValue(null, "codePath");
7499 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007500 version = parser.getAttributeValue(null, "version");
7501 if (version != null) {
7502 try {
7503 versionCode = Integer.parseInt(version);
7504 } catch (NumberFormatException e) {
7505 }
7506 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007507 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007508
7509 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007511 try {
7512 pkgFlags = Integer.parseInt(systemStr);
7513 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 }
7515 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007516 // For backward compatibility
7517 systemStr = parser.getAttributeValue(null, "system");
7518 if (systemStr != null) {
7519 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
7520 } else {
7521 // Old settings that don't specify system... just treat
7522 // them as system, good enough.
7523 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7524 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007525 }
7526 timeStampStr = parser.getAttributeValue(null, "ts");
7527 if (timeStampStr != null) {
7528 try {
7529 timeStamp = Long.parseLong(timeStampStr);
7530 } catch (NumberFormatException e) {
7531 }
7532 }
7533 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7534 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7535 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7536 if (resourcePathStr == null) {
7537 resourcePathStr = codePathStr;
7538 }
7539 if (name == null) {
7540 reportSettingsProblem(Log.WARN,
7541 "Error in package manager settings: <package> has no name at "
7542 + parser.getPositionDescription());
7543 } else if (codePathStr == null) {
7544 reportSettingsProblem(Log.WARN,
7545 "Error in package manager settings: <package> has no codePath at "
7546 + parser.getPositionDescription());
7547 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007548 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007549 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007550 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7551 + ": userId=" + userId + " pkg=" + packageSetting);
7552 if (packageSetting == null) {
7553 reportSettingsProblem(Log.ERROR,
7554 "Failure adding uid " + userId
7555 + " while parsing settings at "
7556 + parser.getPositionDescription());
7557 } else {
7558 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7559 }
7560 } else if (sharedIdStr != null) {
7561 userId = sharedIdStr != null
7562 ? Integer.parseInt(sharedIdStr) : 0;
7563 if (userId > 0) {
7564 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007565 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7567 mPendingPackages.add((PendingPackage) packageSetting);
7568 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7569 + ": sharedUserId=" + userId + " pkg="
7570 + packageSetting);
7571 } else {
7572 reportSettingsProblem(Log.WARN,
7573 "Error in package manager settings: package "
7574 + name + " has bad sharedId " + sharedIdStr
7575 + " at " + parser.getPositionDescription());
7576 }
7577 } else {
7578 reportSettingsProblem(Log.WARN,
7579 "Error in package manager settings: package "
7580 + name + " has bad userId " + idStr + " at "
7581 + parser.getPositionDescription());
7582 }
7583 } catch (NumberFormatException e) {
7584 reportSettingsProblem(Log.WARN,
7585 "Error in package manager settings: package "
7586 + name + " has bad userId " + idStr + " at "
7587 + parser.getPositionDescription());
7588 }
7589 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007590 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 final String enabledStr = parser.getAttributeValue(null, "enabled");
7592 if (enabledStr != null) {
7593 if (enabledStr.equalsIgnoreCase("true")) {
7594 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7595 } else if (enabledStr.equalsIgnoreCase("false")) {
7596 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7597 } else if (enabledStr.equalsIgnoreCase("default")) {
7598 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7599 } else {
7600 reportSettingsProblem(Log.WARN,
7601 "Error in package manager settings: package "
7602 + name + " has bad enabled value: " + idStr
7603 + " at " + parser.getPositionDescription());
7604 }
7605 } else {
7606 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7607 }
7608 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7609 if (installStatusStr != null) {
7610 if (installStatusStr.equalsIgnoreCase("false")) {
7611 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7612 } else {
7613 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7614 }
7615 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007617 int outerDepth = parser.getDepth();
7618 int type;
7619 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7620 && (type != XmlPullParser.END_TAG
7621 || parser.getDepth() > outerDepth)) {
7622 if (type == XmlPullParser.END_TAG
7623 || type == XmlPullParser.TEXT) {
7624 continue;
7625 }
7626
7627 String tagName = parser.getName();
7628 if (tagName.equals("disabled-components")) {
7629 readDisabledComponentsLP(packageSetting, parser);
7630 } else if (tagName.equals("enabled-components")) {
7631 readEnabledComponentsLP(packageSetting, parser);
7632 } else if (tagName.equals("sigs")) {
7633 packageSetting.signatures.readXml(parser, mPastSignatures);
7634 } else if (tagName.equals("perms")) {
7635 readGrantedPermissionsLP(parser,
7636 packageSetting.loadedPermissions);
7637 packageSetting.permissionsFixed = true;
7638 } else {
7639 reportSettingsProblem(Log.WARN,
7640 "Unknown element under <package>: "
7641 + parser.getName());
7642 XmlUtils.skipCurrentTag(parser);
7643 }
7644 }
7645 } else {
7646 XmlUtils.skipCurrentTag(parser);
7647 }
7648 }
7649
7650 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7651 XmlPullParser parser)
7652 throws IOException, XmlPullParserException {
7653 int outerDepth = parser.getDepth();
7654 int type;
7655 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7656 && (type != XmlPullParser.END_TAG
7657 || parser.getDepth() > outerDepth)) {
7658 if (type == XmlPullParser.END_TAG
7659 || type == XmlPullParser.TEXT) {
7660 continue;
7661 }
7662
7663 String tagName = parser.getName();
7664 if (tagName.equals("item")) {
7665 String name = parser.getAttributeValue(null, "name");
7666 if (name != null) {
7667 packageSetting.disabledComponents.add(name.intern());
7668 } else {
7669 reportSettingsProblem(Log.WARN,
7670 "Error in package manager settings: <disabled-components> has"
7671 + " no name at " + parser.getPositionDescription());
7672 }
7673 } else {
7674 reportSettingsProblem(Log.WARN,
7675 "Unknown element under <disabled-components>: "
7676 + parser.getName());
7677 }
7678 XmlUtils.skipCurrentTag(parser);
7679 }
7680 }
7681
7682 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7683 XmlPullParser parser)
7684 throws IOException, XmlPullParserException {
7685 int outerDepth = parser.getDepth();
7686 int type;
7687 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7688 && (type != XmlPullParser.END_TAG
7689 || parser.getDepth() > outerDepth)) {
7690 if (type == XmlPullParser.END_TAG
7691 || type == XmlPullParser.TEXT) {
7692 continue;
7693 }
7694
7695 String tagName = parser.getName();
7696 if (tagName.equals("item")) {
7697 String name = parser.getAttributeValue(null, "name");
7698 if (name != null) {
7699 packageSetting.enabledComponents.add(name.intern());
7700 } else {
7701 reportSettingsProblem(Log.WARN,
7702 "Error in package manager settings: <enabled-components> has"
7703 + " no name at " + parser.getPositionDescription());
7704 }
7705 } else {
7706 reportSettingsProblem(Log.WARN,
7707 "Unknown element under <enabled-components>: "
7708 + parser.getName());
7709 }
7710 XmlUtils.skipCurrentTag(parser);
7711 }
7712 }
7713
7714 private void readSharedUserLP(XmlPullParser parser)
7715 throws XmlPullParserException, IOException {
7716 String name = null;
7717 String idStr = null;
7718 int pkgFlags = 0;
7719 SharedUserSetting su = null;
7720 try {
7721 name = parser.getAttributeValue(null, "name");
7722 idStr = parser.getAttributeValue(null, "userId");
7723 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7724 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7725 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7726 }
7727 if (name == null) {
7728 reportSettingsProblem(Log.WARN,
7729 "Error in package manager settings: <shared-user> has no name at "
7730 + parser.getPositionDescription());
7731 } else if (userId == 0) {
7732 reportSettingsProblem(Log.WARN,
7733 "Error in package manager settings: shared-user "
7734 + name + " has bad userId " + idStr + " at "
7735 + parser.getPositionDescription());
7736 } else {
7737 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7738 reportSettingsProblem(Log.ERROR,
7739 "Occurred while parsing settings at "
7740 + parser.getPositionDescription());
7741 }
7742 }
7743 } catch (NumberFormatException e) {
7744 reportSettingsProblem(Log.WARN,
7745 "Error in package manager settings: package "
7746 + name + " has bad userId " + idStr + " at "
7747 + parser.getPositionDescription());
7748 };
7749
7750 if (su != null) {
7751 int outerDepth = parser.getDepth();
7752 int type;
7753 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7754 && (type != XmlPullParser.END_TAG
7755 || parser.getDepth() > outerDepth)) {
7756 if (type == XmlPullParser.END_TAG
7757 || type == XmlPullParser.TEXT) {
7758 continue;
7759 }
7760
7761 String tagName = parser.getName();
7762 if (tagName.equals("sigs")) {
7763 su.signatures.readXml(parser, mPastSignatures);
7764 } else if (tagName.equals("perms")) {
7765 readGrantedPermissionsLP(parser, su.loadedPermissions);
7766 } else {
7767 reportSettingsProblem(Log.WARN,
7768 "Unknown element under <shared-user>: "
7769 + parser.getName());
7770 XmlUtils.skipCurrentTag(parser);
7771 }
7772 }
7773
7774 } else {
7775 XmlUtils.skipCurrentTag(parser);
7776 }
7777 }
7778
7779 private void readGrantedPermissionsLP(XmlPullParser parser,
7780 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7781 int outerDepth = parser.getDepth();
7782 int type;
7783 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7784 && (type != XmlPullParser.END_TAG
7785 || parser.getDepth() > outerDepth)) {
7786 if (type == XmlPullParser.END_TAG
7787 || type == XmlPullParser.TEXT) {
7788 continue;
7789 }
7790
7791 String tagName = parser.getName();
7792 if (tagName.equals("item")) {
7793 String name = parser.getAttributeValue(null, "name");
7794 if (name != null) {
7795 outPerms.add(name.intern());
7796 } else {
7797 reportSettingsProblem(Log.WARN,
7798 "Error in package manager settings: <perms> has"
7799 + " no name at " + parser.getPositionDescription());
7800 }
7801 } else {
7802 reportSettingsProblem(Log.WARN,
7803 "Unknown element under <perms>: "
7804 + parser.getName());
7805 }
7806 XmlUtils.skipCurrentTag(parser);
7807 }
7808 }
7809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 private void readPreferredActivitiesLP(XmlPullParser parser)
7811 throws XmlPullParserException, IOException {
7812 int outerDepth = parser.getDepth();
7813 int type;
7814 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7815 && (type != XmlPullParser.END_TAG
7816 || parser.getDepth() > outerDepth)) {
7817 if (type == XmlPullParser.END_TAG
7818 || type == XmlPullParser.TEXT) {
7819 continue;
7820 }
7821
7822 String tagName = parser.getName();
7823 if (tagName.equals("item")) {
7824 PreferredActivity pa = new PreferredActivity(parser);
7825 if (pa.mParseError == null) {
7826 mPreferredActivities.addFilter(pa);
7827 } else {
7828 reportSettingsProblem(Log.WARN,
7829 "Error in package manager settings: <preferred-activity> "
7830 + pa.mParseError + " at "
7831 + parser.getPositionDescription());
7832 }
7833 } else {
7834 reportSettingsProblem(Log.WARN,
7835 "Unknown element under <preferred-activities>: "
7836 + parser.getName());
7837 XmlUtils.skipCurrentTag(parser);
7838 }
7839 }
7840 }
7841
7842 // Returns -1 if we could not find an available UserId to assign
7843 private int newUserIdLP(Object obj) {
7844 // Let's be stupidly inefficient for now...
7845 final int N = mUserIds.size();
7846 for (int i=0; i<N; i++) {
7847 if (mUserIds.get(i) == null) {
7848 mUserIds.set(i, obj);
7849 return FIRST_APPLICATION_UID + i;
7850 }
7851 }
7852
7853 // None left?
7854 if (N >= MAX_APPLICATION_UIDS) {
7855 return -1;
7856 }
7857
7858 mUserIds.add(obj);
7859 return FIRST_APPLICATION_UID + N;
7860 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 public PackageSetting getDisabledSystemPkg(String name) {
7863 synchronized(mPackages) {
7864 PackageSetting ps = mDisabledSysPackages.get(name);
7865 return ps;
7866 }
7867 }
7868
7869 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7870 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7871 if (Config.LOGV) {
7872 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7873 + " componentName = " + componentInfo.name);
7874 Log.v(TAG, "enabledComponents: "
7875 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7876 Log.v(TAG, "disabledComponents: "
7877 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7878 }
7879 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7880 || ((componentInfo.enabled
7881 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7882 || (componentInfo.applicationInfo.enabled
7883 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7884 && !packageSettings.disabledComponents.contains(componentInfo.name))
7885 || packageSettings.enabledComponents.contains(componentInfo.name));
7886 }
7887 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007888
7889 // ------- apps on sdcard specific code -------
7890 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08007891 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08007892 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007893 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007894 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007895
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007896
7897 static MountService getMountService() {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007898 return (MountService) ServiceManager.getService("mount");
7899 }
7900
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007901 private String getEncryptKey() {
7902 try {
7903 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7904 if (sdEncKey == null) {
7905 sdEncKey = SystemKeyStore.getInstance().
7906 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
7907 if (sdEncKey == null) {
7908 Log.e(TAG, "Failed to create encryption keys");
7909 return null;
7910 }
7911 }
7912 return sdEncKey;
7913 } catch (NoSuchAlgorithmException nsae) {
7914 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
7915 return null;
7916 }
7917 }
7918
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007919 private String createSdDir(File tmpPackageFile, String pkgName) {
7920 // Create mount point via MountService
7921 MountService mountService = getMountService();
7922 long len = tmpPackageFile.length();
7923 int mbLen = (int) (len/(1024*1024));
7924 if ((len - (mbLen * 1024 * 1024)) > 0) {
7925 mbLen++;
7926 }
7927 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
7928 String cachePath = null;
Oscar Montemayord02546b2010-01-14 16:38:40 -08007929 String sdEncKey;
7930 try {
7931 sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7932 if (sdEncKey == null) {
7933 sdEncKey = SystemKeyStore.getInstance().
7934 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
7935 if (sdEncKey == null) {
7936 Log.e(TAG, "Failed to create encryption keys for package: " + pkgName + ".");
7937 return null;
7938 }
7939 }
7940 } catch (NoSuchAlgorithmException nsae) {
7941 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
7942 return null;
7943 }
San Mehatbe16cb12010-01-29 05:35:35 -08007944
7945 int rc = mountService.createSecureContainer(
7946 pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
7947 if (rc != MountServiceResultCode.OperationSucceeded) {
7948 Log.e(TAG, String.format("Failed to create container (%d)", rc));
7949
7950 rc = mountService.destroySecureContainer(pkgName);
7951 if (rc != MountServiceResultCode.OperationSucceeded) {
7952 Log.e(TAG, String.format("Failed to cleanup container (%d)", rc));
7953 return null;
7954 }
7955 rc = mountService.createSecureContainer(
7956 pkgName, mbLen, "vfat", sdEncKey, Process.SYSTEM_UID);
7957 if (rc != MountServiceResultCode.OperationSucceeded) {
7958 Log.e(TAG, String.format("Failed to create container (2nd try) (%d)", rc));
7959 return null;
7960 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007961 }
San Mehatbe16cb12010-01-29 05:35:35 -08007962
7963 cachePath = mountService.getSecureContainerPath(pkgName);
7964 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007965 return cachePath;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007966 }
7967
7968 private String mountSdDir(String pkgName, int ownerUid) {
Oscar Montemayord02546b2010-01-14 16:38:40 -08007969 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7970 if (sdEncKey == null) {
7971 Log.e(TAG, "Failed to retrieve encryption keys to mount package code: " + pkgName + ".");
7972 return null;
7973 }
San Mehatbe16cb12010-01-29 05:35:35 -08007974
7975 int rc = getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
7976
7977 if (rc != MountServiceResultCode.OperationSucceeded) {
7978 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " rc : " + rc);
7979 return null;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007980 }
San Mehatbe16cb12010-01-29 05:35:35 -08007981
7982 return getMountService().getSecureContainerPath(pkgName);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007983 }
7984
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007985 private boolean unMountSdDir(String pkgName) {
7986 // STOPSHIP unmount directory
San Mehatbe16cb12010-01-29 05:35:35 -08007987 int rc = getMountService().unmountSecureContainer(pkgName);
7988 if (rc != MountServiceResultCode.OperationSucceeded) {
7989 Log.e(TAG, "Failed to unmount : " + pkgName + " with rc " + rc);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007990 return false;
7991 }
San Mehatbe16cb12010-01-29 05:35:35 -08007992 return true;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007993 }
7994
San Mehatbe16cb12010-01-29 05:35:35 -08007995 private String getSdDir(String pkgName) {
7996 return getMountService().getSecureContainerPath(pkgName);
7997 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007998
San Mehatbe16cb12010-01-29 05:35:35 -08007999 private boolean finalizeSdDir(String pkgName) {
8000 int rc = getMountService().finalizeSecureContainer(pkgName);
8001 if (rc != MountServiceResultCode.OperationSucceeded) {
8002 Log.i(TAG, "Failed to finalize container for pkg : " + pkgName);
8003 return false;
8004 }
8005 return true;
8006 }
8007
8008 private boolean destroySdDir(String pkgName) {
8009 int rc = getMountService().destroySecureContainer(pkgName);
8010 if (rc != MountServiceResultCode.OperationSucceeded) {
8011 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
8012 return false;
8013 }
8014 return true;
8015 }
8016
8017 static String[] getSecureContainerList() {
8018 String[] list = getMountService().getSecureContainerList();
8019 return list.length == 0 ? null : list;
8020 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008021
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008022 static String getTempContainerId() {
8023 String prefix = "smdl1tmp";
8024 int tmpIdx = 1;
8025 String list[] = getSecureContainerList();
8026 if (list != null) {
8027 int idx = 0;
8028 int idList[] = new int[MAX_CONTAINERS];
8029 boolean neverFound = true;
8030 for (String name : list) {
8031 // Ignore null entries
8032 if (name == null) {
8033 continue;
8034 }
8035 int sidx = name.indexOf(prefix);
8036 if (sidx == -1) {
8037 // Not a temp file. just ignore
8038 continue;
8039 }
8040 String subStr = name.substring(sidx + prefix.length());
8041 idList[idx] = -1;
8042 if (subStr != null) {
8043 try {
8044 int cid = Integer.parseInt(subStr);
8045 idList[idx++] = cid;
8046 neverFound = false;
8047 } catch (NumberFormatException e) {
8048 }
8049 }
8050 }
8051 if (!neverFound) {
8052 // Sort idList
8053 Arrays.sort(idList);
8054 for (int j = 1; j <= idList.length; j++) {
8055 if (idList[j-1] != j) {
8056 tmpIdx = j;
8057 break;
8058 }
8059 }
8060 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008061 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008062 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008063 }
8064
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008065 public void updateExternalMediaStatus(final boolean mediaStatus) {
8066 if (mediaStatus == mMediaMounted) {
8067 return;
8068 }
8069 mMediaMounted = mediaStatus;
8070 // Queue up an async operation since the package installation may take a little while.
8071 mHandler.post(new Runnable() {
8072 public void run() {
8073 mHandler.removeCallbacks(this);
8074 final String list[] = getSecureContainerList();
8075 if (list == null || list.length == 0) {
8076 return;
8077 }
8078 for (int i = 0; i < list.length; i++) {
8079 String mountPkg = list[i];
8080 // TODO compare with default package
8081 synchronized (mPackages) {
8082 PackageSetting ps = mSettings.mPackages.get(mountPkg);
8083 if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
8084 if (mediaStatus) {
8085 String pkgPath = getSdDir(mountPkg);
8086 if (pkgPath == null) {
8087 continue;
8088 }
8089 pkgPath = ps.codePathString;
8090 int parseFlags = PackageParser.PARSE_CHATTY |
8091 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8092 PackageParser pp = new PackageParser(pkgPath);
8093 pp.setSeparateProcesses(mSeparateProcesses);
8094 final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
8095 null, mMetrics, parseFlags);
8096 if (pkg == null) {
8097 Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
8098 continue;
8099 }
8100 int scanMode = SCAN_MONITOR;
8101 // Scan the package
8102 if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
8103 // Grant permissions
8104 grantPermissionsLP(pkg, false);
8105 // Persist settings
8106 mSettings.writeLP();
8107 } else {
8108 Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
8109 }
8110 } else {
8111 // Delete package
8112 PackageRemovedInfo outInfo = new PackageRemovedInfo();
8113 boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
8114 if (!res) {
8115 Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
8116 }
8117 }
8118 }
8119 }
8120 }
8121 }
8122 });
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008124}