blob: 1cf3badb25559d27e9148ddbd63cfd8bf8b6cca9 [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;
76import android.os.ParcelFileDescriptor;
77import android.os.Process;
78import android.os.ServiceManager;
79import android.os.SystemClock;
80import android.os.SystemProperties;
Oscar Montemayord02546b2010-01-14 16:38:40 -080081import android.security.SystemKeyStore;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.util.*;
83import android.view.Display;
84import android.view.WindowManager;
85
86import java.io.File;
87import java.io.FileDescriptor;
88import java.io.FileInputStream;
89import java.io.FileNotFoundException;
90import java.io.FileOutputStream;
91import java.io.FileReader;
92import java.io.FilenameFilter;
93import java.io.IOException;
94import java.io.InputStream;
95import java.io.PrintWriter;
Oscar Montemayord02546b2010-01-14 16:38:40 -080096import java.security.NoSuchAlgorithmException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import java.util.ArrayList;
98import java.util.Arrays;
Dianne Hackborn49237342009-08-27 20:08:01 -070099import java.util.Collection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import java.util.Collections;
101import java.util.Comparator;
102import java.util.Enumeration;
103import java.util.HashMap;
104import java.util.HashSet;
105import java.util.Iterator;
106import java.util.List;
107import java.util.Map;
108import java.util.Set;
109import java.util.zip.ZipEntry;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -0800110import java.util.zip.ZipException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.util.zip.ZipFile;
112import java.util.zip.ZipOutputStream;
113
114class PackageManagerService extends IPackageManager.Stub {
115 private static final String TAG = "PackageManager";
116 private static final boolean DEBUG_SETTINGS = false;
117 private static final boolean DEBUG_PREFERRED = false;
118
119 private static final boolean MULTIPLE_APPLICATION_UIDS = true;
120 private static final int RADIO_UID = Process.PHONE_UID;
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400121 private static final int LOG_UID = Process.LOG_UID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 private static final int FIRST_APPLICATION_UID =
123 Process.FIRST_APPLICATION_UID;
124 private static final int MAX_APPLICATION_UIDS = 1000;
125
126 private static final boolean SHOW_INFO = false;
127
128 private static final boolean GET_CERTIFICATES = true;
129
Oscar Montemayora8529f62009-11-18 10:14:20 -0800130 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 private static final int REMOVE_EVENTS =
133 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
134 private static final int ADD_EVENTS =
135 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
136
137 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
138
139 static final int SCAN_MONITOR = 1<<0;
140 static final int SCAN_NO_DEX = 1<<1;
141 static final int SCAN_FORCE_DEX = 1<<2;
142 static final int SCAN_UPDATE_SIGNATURE = 1<<3;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800143 static final int SCAN_NEW_INSTALL = 1<<4;
144 static final int SCAN_NO_PATHS = 1<<5;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
146 final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
147 Process.THREAD_PRIORITY_BACKGROUND);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700148 final PackageHandler mHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149
Dianne Hackborn851a5412009-05-08 12:06:44 -0700150 final int mSdkVersion = Build.VERSION.SDK_INT;
151 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
152 ? null : Build.VERSION.CODENAME;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 final Context mContext;
155 final boolean mFactoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700156 final boolean mNoDexOpt;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 final DisplayMetrics mMetrics;
158 final int mDefParseFlags;
159 final String[] mSeparateProcesses;
160
161 // This is where all application persistent data goes.
162 final File mAppDataDir;
163
Oscar Montemayora8529f62009-11-18 10:14:20 -0800164 // If Encrypted File System feature is enabled, all application persistent data
165 // should go here instead.
166 final File mSecureAppDataDir;
167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 // This is the object monitoring the framework dir.
169 final FileObserver mFrameworkInstallObserver;
170
171 // This is the object monitoring the system app dir.
172 final FileObserver mSystemInstallObserver;
173
174 // This is the object monitoring mAppInstallDir.
175 final FileObserver mAppInstallObserver;
176
177 // This is the object monitoring mDrmAppPrivateInstallDir.
178 final FileObserver mDrmAppInstallObserver;
179
180 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages
181 // LOCK HELD. Can be called with mInstallLock held.
182 final Installer mInstaller;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 final File mFrameworkDir;
185 final File mSystemAppDir;
186 final File mAppInstallDir;
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700187 final File mDalvikCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188
189 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
190 // apps.
191 final File mDrmAppPrivateInstallDir;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 // Lock for state used when installing and doing other long running
196 // operations. Methods that must be called with this lock held have
197 // the prefix "LI".
198 final Object mInstallLock = new Object();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 // These are the directories in the 3rd party applications installed dir
201 // that we have currently loaded packages from. Keys are the application's
202 // installed zip file (absolute codePath), and values are Package.
203 final HashMap<String, PackageParser.Package> mAppDirs =
204 new HashMap<String, PackageParser.Package>();
205
206 // Information for the parser to write more useful error messages.
207 File mScanningPath;
208 int mLastScanError;
209
210 final int[] mOutPermissions = new int[3];
211
212 // ----------------------------------------------------------------
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 // Keys are String (package name), values are Package. This also serves
215 // as the lock for the global state. Methods that must be called with
216 // this lock held have the prefix "LP".
217 final HashMap<String, PackageParser.Package> mPackages =
218 new HashMap<String, PackageParser.Package>();
219
220 final Settings mSettings;
221 boolean mRestoredSettings;
222 boolean mReportedUidError;
223
224 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
225 int[] mGlobalGids;
226
227 // These are the built-in uid -> permission mappings that were read from the
228 // etc/permissions.xml file.
229 final SparseArray<HashSet<String>> mSystemPermissions =
230 new SparseArray<HashSet<String>>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 // These are the built-in shared libraries that were read from the
233 // etc/permissions.xml file.
234 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800235
Dianne Hackborn49237342009-08-27 20:08:01 -0700236 // Temporary for building the final shared libraries for an .apk.
237 String[] mTmpSharedLibraries = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800238
Dianne Hackborn49237342009-08-27 20:08:01 -0700239 // These are the features this devices supports that were read from the
240 // etc/permissions.xml file.
241 final HashMap<String, FeatureInfo> mAvailableFeatures =
242 new HashMap<String, FeatureInfo>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 // All available activities, for your resolving pleasure.
245 final ActivityIntentResolver mActivities =
246 new ActivityIntentResolver();
247
248 // All available receivers, for your resolving pleasure.
249 final ActivityIntentResolver mReceivers =
250 new ActivityIntentResolver();
251
252 // All available services, for your resolving pleasure.
253 final ServiceIntentResolver mServices = new ServiceIntentResolver();
254
255 // Keys are String (provider class name), values are Provider.
256 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
257 new HashMap<ComponentName, PackageParser.Provider>();
258
259 // Mapping from provider base names (first directory in content URI codePath)
260 // to the provider information.
261 final HashMap<String, PackageParser.Provider> mProviders =
262 new HashMap<String, PackageParser.Provider>();
263
264 // Mapping from instrumentation class names to info about them.
265 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
266 new HashMap<ComponentName, PackageParser.Instrumentation>();
267
268 // Mapping from permission names to info about them.
269 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups =
270 new HashMap<String, PackageParser.PermissionGroup>();
271
Dianne Hackborn854060af2009-07-09 18:14:31 -0700272 // Broadcast actions that are only available to the system.
273 final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 boolean mSystemReady;
276 boolean mSafeMode;
277 boolean mHasSystemUidErrors;
278
279 ApplicationInfo mAndroidApplication;
280 final ActivityInfo mResolveActivity = new ActivityInfo();
281 final ResolveInfo mResolveInfo = new ResolveInfo();
282 ComponentName mResolveComponentName;
283 PackageParser.Package mPlatformPackage;
284
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700285 // Set of pending broadcasts for aggregating enable/disable of components.
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800286 final HashMap<String, ArrayList<String>> mPendingBroadcasts
287 = new HashMap<String, ArrayList<String>>();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700288 static final int SEND_PENDING_BROADCAST = 1;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800289 static final int MCS_BOUND = 3;
290 static final int END_COPY = 4;
291 static final int INIT_COPY = 5;
292 static final int MCS_UNBIND = 6;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700293 // Delay time in millisecs
294 static final int BROADCAST_DELAY = 10 * 1000;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800295 private ServiceConnection mDefContainerConn = new ServiceConnection() {
296 public void onServiceConnected(ComponentName name, IBinder service) {
297 IMediaContainerService imcs =
298 IMediaContainerService.Stub.asInterface(service);
299 Message msg = mHandler.obtainMessage(MCS_BOUND, imcs);
300 mHandler.sendMessage(msg);
301 }
302
303 public void onServiceDisconnected(ComponentName name) {
304 }
305 };
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700306
307 class PackageHandler extends Handler {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800308 final ArrayList<InstallArgs> mPendingInstalls =
309 new ArrayList<InstallArgs>();
310 // Service Connection to remote media container service to copy
311 // package uri's from external media onto secure containers
312 // or internal storage.
313 private IMediaContainerService mContainerService = null;
314
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700315 PackageHandler(Looper looper) {
316 super(looper);
317 }
318 public void handleMessage(Message msg) {
319 switch (msg.what) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800320 case INIT_COPY: {
321 InstallArgs args = (InstallArgs) msg.obj;
322 args.createCopyFile();
323 Intent service = new Intent().setComponent(new ComponentName(
324 "com.android.defcontainer",
325 "com.android.defcontainer.DefaultContainerService"));
326 if (mContainerService != null) {
327 // No need to add to pending list. Use remote stub directly
328 handleStartCopy(args);
329 } else {
330 if (mContext.bindService(service, mDefContainerConn,
331 Context.BIND_AUTO_CREATE)) {
332 mPendingInstalls.add(args);
333 } else {
334 Log.e(TAG, "Failed to bind to media container service");
335 // Indicate install failure TODO add new error code
336 processPendingInstall(args,
337 PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800338 }
339 }
340 break;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800341 }
342 case MCS_BOUND: {
343 // Initialize mContainerService if needed.
344 if (msg.obj != null) {
345 mContainerService = (IMediaContainerService) msg.obj;
346 }
347 if (mPendingInstalls.size() > 0) {
348 InstallArgs args = mPendingInstalls.remove(0);
349 if (args != null) {
350 handleStartCopy(args);
351 }
352 }
353 break;
354 }
355 case MCS_UNBIND : {
356 if (mPendingInstalls.size() == 0) {
357 mContext.unbindService(mDefContainerConn);
358 mContainerService = null;
359 }
360 break;
361 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700362 case SEND_PENDING_BROADCAST : {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800363 String packages[];
364 ArrayList components[];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700365 int size = 0;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700366 int uids[];
367 synchronized (mPackages) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800368 if (mPendingBroadcasts == null) {
369 return;
370 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700371 size = mPendingBroadcasts.size();
372 if (size <= 0) {
373 // Nothing to be done. Just return
374 return;
375 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800376 packages = new String[size];
377 components = new ArrayList[size];
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700378 uids = new int[size];
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800379 Iterator<HashMap.Entry<String, ArrayList<String>>>
380 it = mPendingBroadcasts.entrySet().iterator();
381 int i = 0;
382 while (it.hasNext() && i < size) {
383 HashMap.Entry<String, ArrayList<String>> ent = it.next();
384 packages[i] = ent.getKey();
385 components[i] = ent.getValue();
386 PackageSetting ps = mSettings.mPackages.get(ent.getKey());
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700387 uids[i] = (ps != null) ? ps.userId : -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800388 i++;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700389 }
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800390 size = i;
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700391 mPendingBroadcasts.clear();
392 }
393 // Send broadcasts
394 for (int i = 0; i < size; i++) {
Dianne Hackborn86a72da2009-11-11 20:12:41 -0800395 sendPackageChangedBroadcast(packages[i], true,
396 (ArrayList<String>)components[i], uids[i]);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700397 }
398 break;
399 }
400 }
401 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800402
403 // Utility method to initiate copying apk via media
404 // container service.
405 private void handleStartCopy(InstallArgs args) {
406 int ret = PackageManager.INSTALL_SUCCEEDED;
407 if (mContainerService == null) {
408 // Install error
409 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
410 } else {
411 ret = args.copyApk(mContainerService);
412 }
413 mHandler.sendEmptyMessage(MCS_UNBIND);
414 processPendingInstall(args, ret);
415 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700416 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -0800417
418 static boolean installOnSd(int flags) {
419 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
420 ((flags & PackageManager.INSTALL_ON_SDCARD) == 0)) {
421 return false;
422 }
423 return true;
424 }
425
426 static boolean isFwdLocked(int flags) {
427 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
428 return true;
429 }
430 return false;
431 }
432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 public static final IPackageManager main(Context context, boolean factoryTest) {
434 PackageManagerService m = new PackageManagerService(context, factoryTest);
435 ServiceManager.addService("package", m);
436 return m;
437 }
438
439 static String[] splitString(String str, char sep) {
440 int count = 1;
441 int i = 0;
442 while ((i=str.indexOf(sep, i)) >= 0) {
443 count++;
444 i++;
445 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 String[] res = new String[count];
448 i=0;
449 count = 0;
450 int lastI=0;
451 while ((i=str.indexOf(sep, i)) >= 0) {
452 res[count] = str.substring(lastI, i);
453 count++;
454 i++;
455 lastI = i;
456 }
457 res[count] = str.substring(lastI, str.length());
458 return res;
459 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 public PackageManagerService(Context context, boolean factoryTest) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800462 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 if (mSdkVersion <= 0) {
466 Log.w(TAG, "**** ro.build.version.sdk not set!");
467 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 mContext = context;
470 mFactoryTest = factoryTest;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700471 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 mMetrics = new DisplayMetrics();
473 mSettings = new Settings();
474 mSettings.addSharedUserLP("android.uid.system",
475 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
476 mSettings.addSharedUserLP("android.uid.phone",
477 MULTIPLE_APPLICATION_UIDS
478 ? RADIO_UID : FIRST_APPLICATION_UID,
479 ApplicationInfo.FLAG_SYSTEM);
Mike Lockwoodd42685d2009-09-03 09:25:22 -0400480 mSettings.addSharedUserLP("android.uid.log",
481 MULTIPLE_APPLICATION_UIDS
482 ? LOG_UID : FIRST_APPLICATION_UID,
483 ApplicationInfo.FLAG_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484
485 String separateProcesses = SystemProperties.get("debug.separate_processes");
486 if (separateProcesses != null && separateProcesses.length() > 0) {
487 if ("*".equals(separateProcesses)) {
488 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
489 mSeparateProcesses = null;
490 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
491 } else {
492 mDefParseFlags = 0;
493 mSeparateProcesses = separateProcesses.split(",");
494 Log.w(TAG, "Running with debug.separate_processes: "
495 + separateProcesses);
496 }
497 } else {
498 mDefParseFlags = 0;
499 mSeparateProcesses = null;
500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 Installer installer = new Installer();
503 // Little hacky thing to check if installd is here, to determine
504 // whether we are running on the simulator and thus need to take
505 // care of building the /data file structure ourself.
506 // (apparently the sim now has a working installer)
507 if (installer.ping() && Process.supportsProcesses()) {
508 mInstaller = installer;
509 } else {
510 mInstaller = null;
511 }
512
513 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
514 Display d = wm.getDefaultDisplay();
515 d.getMetrics(mMetrics);
516
517 synchronized (mInstallLock) {
518 synchronized (mPackages) {
519 mHandlerThread.start();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -0700520 mHandler = new PackageHandler(mHandlerThread.getLooper());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 File dataDir = Environment.getDataDirectory();
523 mAppDataDir = new File(dataDir, "data");
Oscar Montemayora8529f62009-11-18 10:14:20 -0800524 mSecureAppDataDir = new File(dataDir, "secure/data");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
526
527 if (mInstaller == null) {
528 // Make sure these dirs exist, when we are running in
529 // the simulator.
530 // Make a wide-open directory for random misc stuff.
531 File miscDir = new File(dataDir, "misc");
532 miscDir.mkdirs();
533 mAppDataDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -0800534 mSecureAppDataDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 mDrmAppPrivateInstallDir.mkdirs();
536 }
537
538 readPermissions();
539
540 mRestoredSettings = mSettings.readLP();
541 long startTime = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800542
543 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 startTime);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800545
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800546 // Set flag to monitor and not change apk file paths when
547 // scanning install directories.
548 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700549 if (mNoDexOpt) {
550 Log.w(TAG, "Running ENG build: no pre-dexopt!");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800551 scanMode |= SCAN_NO_DEX;
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700552 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 final HashSet<String> libFiles = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700557 mDalvikCacheDir = new File(dataDir, "dalvik-cache");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 if (mInstaller != null) {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700560 boolean didDexOpt = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 /**
563 * Out of paranoia, ensure that everything in the boot class
564 * path has been dexed.
565 */
566 String bootClassPath = System.getProperty("java.boot.class.path");
567 if (bootClassPath != null) {
568 String[] paths = splitString(bootClassPath, ':');
569 for (int i=0; i<paths.length; i++) {
570 try {
571 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
572 libFiles.add(paths[i]);
573 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700574 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 }
576 } catch (FileNotFoundException e) {
577 Log.w(TAG, "Boot class path not found: " + paths[i]);
578 } catch (IOException e) {
579 Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
580 }
581 }
582 } else {
583 Log.w(TAG, "No BOOTCLASSPATH found!");
584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586 /**
587 * Also ensure all external libraries have had dexopt run on them.
588 */
589 if (mSharedLibraries.size() > 0) {
590 Iterator<String> libs = mSharedLibraries.values().iterator();
591 while (libs.hasNext()) {
592 String lib = libs.next();
593 try {
594 if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
595 libFiles.add(lib);
596 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700597 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 }
599 } catch (FileNotFoundException e) {
600 Log.w(TAG, "Library not found: " + lib);
601 } catch (IOException e) {
602 Log.w(TAG, "Exception reading library: " + lib, e);
603 }
604 }
605 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 // Gross hack for now: we know this file doesn't contain any
608 // code, so don't dexopt it to avoid the resulting log spew.
609 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 /**
612 * And there are a number of commands implemented in Java, which
613 * we currently need to do the dexopt on so that they can be
614 * run from a non-root shell.
615 */
616 String[] frameworkFiles = mFrameworkDir.list();
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700617 if (frameworkFiles != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 for (int i=0; i<frameworkFiles.length; i++) {
619 File libPath = new File(mFrameworkDir, frameworkFiles[i]);
620 String path = libPath.getPath();
621 // Skip the file if we alrady did it.
622 if (libFiles.contains(path)) {
623 continue;
624 }
625 // Skip the file if it is not a type we want to dexopt.
626 if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
627 continue;
628 }
629 try {
630 if (dalvik.system.DexFile.isDexOptNeeded(path)) {
631 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700632 didDexOpt = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 }
634 } catch (FileNotFoundException e) {
635 Log.w(TAG, "Jar not found: " + path);
636 } catch (IOException e) {
637 Log.w(TAG, "Exception reading jar: " + path, e);
638 }
639 }
640 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800641
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700642 if (didDexOpt) {
643 // If we had to do a dexopt of one of the previous
644 // things, then something on the system has changed.
645 // Consider this significant, and wipe away all other
646 // existing dexopt files to ensure we don't leave any
647 // dangling around.
648 String[] files = mDalvikCacheDir.list();
649 if (files != null) {
650 for (int i=0; i<files.length; i++) {
651 String fn = files[i];
652 if (fn.startsWith("data@app@")
653 || fn.startsWith("data@app-private@")) {
654 Log.i(TAG, "Pruning dalvik file: " + fn);
655 (new File(mDalvikCacheDir, fn)).delete();
656 }
657 }
658 }
659 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 mFrameworkInstallObserver = new AppDirObserver(
663 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
664 mFrameworkInstallObserver.startWatching();
665 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800666 scanMode | SCAN_NO_DEX);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 mSystemAppDir = new File(Environment.getRootDirectory(), "app");
668 mSystemInstallObserver = new AppDirObserver(
669 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
670 mSystemInstallObserver.startWatching();
Suchi Amalapurapudaec17222010-01-14 21:25:16 -0800671 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 mAppInstallDir = new File(dataDir, "app");
673 if (mInstaller == null) {
674 // Make sure these dirs exist, when we are running in
675 // the simulator.
676 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists
677 }
678 //look for any incomplete package installations
Oscar Montemayora8529f62009-11-18 10:14:20 -0800679 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 //clean up list
681 for(int i = 0; i < deletePkgsList.size(); i++) {
682 //clean up here
683 cleanupInstallFailedPackage(deletePkgsList.get(i));
684 }
685 //delete tmp files
686 deleteTempPackageFiles();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800687
688 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 SystemClock.uptimeMillis());
690 mAppInstallObserver = new AppDirObserver(
691 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
692 mAppInstallObserver.startWatching();
693 scanDirLI(mAppInstallDir, 0, scanMode);
694
695 mDrmAppInstallObserver = new AppDirObserver(
696 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
697 mDrmAppInstallObserver.startWatching();
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -0800698 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800700 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 SystemClock.uptimeMillis());
702 Log.i(TAG, "Time to scan packages: "
703 + ((SystemClock.uptimeMillis()-startTime)/1000f)
704 + " seconds");
705
706 updatePermissionsLP();
707
708 mSettings.writeLP();
709
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800710 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 SystemClock.uptimeMillis());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 // Now after opening every single application zip, make sure they
714 // are all flushed. Not really needed, but keeps things nice and
715 // tidy.
716 Runtime.getRuntime().gc();
717 } // synchronized (mPackages)
718 } // synchronized (mInstallLock)
719 }
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -0700720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 @Override
722 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
723 throws RemoteException {
724 try {
725 return super.onTransact(code, data, reply, flags);
726 } catch (RuntimeException e) {
727 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
728 Log.e(TAG, "Package Manager Crash", e);
729 }
730 throw e;
731 }
732 }
733
Oscar Montemayora8529f62009-11-18 10:14:20 -0800734 void cleanupInstallFailedPackage(PackageSetting pkgSettings) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800736 boolean useSecureFS = useEncryptedFilesystemForPackage(pkgSettings.pkg);
737 int retCode = mInstaller.remove(pkgSettings.name, useSecureFS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738 if (retCode < 0) {
739 Log.w(TAG, "Couldn't remove app data directory for package: "
Oscar Montemayora8529f62009-11-18 10:14:20 -0800740 + pkgSettings.name + ", retcode=" + retCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 }
742 } else {
743 //for emulator
Oscar Montemayora8529f62009-11-18 10:14:20 -0800744 File dataDir = new File(pkgSettings.pkg.applicationInfo.dataDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 dataDir.delete();
746 }
Oscar Montemayora8529f62009-11-18 10:14:20 -0800747 mSettings.removePackageLP(pkgSettings.name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 }
749
750 void readPermissions() {
751 // Read permissions from .../etc/permission directory.
752 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
753 if (!libraryDir.exists() || !libraryDir.isDirectory()) {
754 Log.w(TAG, "No directory " + libraryDir + ", skipping");
755 return;
756 }
757 if (!libraryDir.canRead()) {
758 Log.w(TAG, "Directory " + libraryDir + " cannot be read");
759 return;
760 }
761
762 // Iterate over the files in the directory and scan .xml files
763 for (File f : libraryDir.listFiles()) {
764 // We'll read platform.xml last
765 if (f.getPath().endsWith("etc/permissions/platform.xml")) {
766 continue;
767 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 if (!f.getPath().endsWith(".xml")) {
770 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
771 continue;
772 }
773 if (!f.canRead()) {
774 Log.w(TAG, "Permissions library file " + f + " cannot be read");
775 continue;
776 }
777
778 readPermissionsFromXml(f);
779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
782 final File permFile = new File(Environment.getRootDirectory(),
783 "etc/permissions/platform.xml");
784 readPermissionsFromXml(permFile);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800785
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700786 StringBuilder sb = new StringBuilder(128);
787 sb.append("Libs:");
788 Iterator<String> it = mSharedLibraries.keySet().iterator();
789 while (it.hasNext()) {
790 sb.append(' ');
791 String name = it.next();
792 sb.append(name);
793 sb.append(':');
794 sb.append(mSharedLibraries.get(name));
795 }
796 Log.i(TAG, sb.toString());
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800797
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700798 sb.setLength(0);
799 sb.append("Features:");
800 it = mAvailableFeatures.keySet().iterator();
801 while (it.hasNext()) {
802 sb.append(' ');
803 sb.append(it.next());
804 }
805 Log.i(TAG, sb.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800807
808 private void readPermissionsFromXml(File permFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 FileReader permReader = null;
810 try {
811 permReader = new FileReader(permFile);
812 } catch (FileNotFoundException e) {
813 Log.w(TAG, "Couldn't find or open permissions file " + permFile);
814 return;
815 }
816
817 try {
818 XmlPullParser parser = Xml.newPullParser();
819 parser.setInput(permReader);
820
821 XmlUtils.beginDocument(parser, "permissions");
822
823 while (true) {
824 XmlUtils.nextElement(parser);
825 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
826 break;
827 }
828
829 String name = parser.getName();
830 if ("group".equals(name)) {
831 String gidStr = parser.getAttributeValue(null, "gid");
832 if (gidStr != null) {
833 int gid = Integer.parseInt(gidStr);
834 mGlobalGids = appendInt(mGlobalGids, gid);
835 } else {
836 Log.w(TAG, "<group> without gid at "
837 + parser.getPositionDescription());
838 }
839
840 XmlUtils.skipCurrentTag(parser);
841 continue;
842 } else if ("permission".equals(name)) {
843 String perm = parser.getAttributeValue(null, "name");
844 if (perm == null) {
845 Log.w(TAG, "<permission> without name at "
846 + parser.getPositionDescription());
847 XmlUtils.skipCurrentTag(parser);
848 continue;
849 }
850 perm = perm.intern();
851 readPermission(parser, perm);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 } else if ("assign-permission".equals(name)) {
854 String perm = parser.getAttributeValue(null, "name");
855 if (perm == null) {
856 Log.w(TAG, "<assign-permission> without name at "
857 + parser.getPositionDescription());
858 XmlUtils.skipCurrentTag(parser);
859 continue;
860 }
861 String uidStr = parser.getAttributeValue(null, "uid");
862 if (uidStr == null) {
863 Log.w(TAG, "<assign-permission> without uid at "
864 + parser.getPositionDescription());
865 XmlUtils.skipCurrentTag(parser);
866 continue;
867 }
868 int uid = Process.getUidForName(uidStr);
869 if (uid < 0) {
870 Log.w(TAG, "<assign-permission> with unknown uid \""
871 + uidStr + "\" at "
872 + parser.getPositionDescription());
873 XmlUtils.skipCurrentTag(parser);
874 continue;
875 }
876 perm = perm.intern();
877 HashSet<String> perms = mSystemPermissions.get(uid);
878 if (perms == null) {
879 perms = new HashSet<String>();
880 mSystemPermissions.put(uid, perms);
881 }
882 perms.add(perm);
883 XmlUtils.skipCurrentTag(parser);
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 } else if ("library".equals(name)) {
886 String lname = parser.getAttributeValue(null, "name");
887 String lfile = parser.getAttributeValue(null, "file");
888 if (lname == null) {
889 Log.w(TAG, "<library> without name at "
890 + parser.getPositionDescription());
891 } else if (lfile == null) {
892 Log.w(TAG, "<library> without file at "
893 + parser.getPositionDescription());
894 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700895 //Log.i(TAG, "Got library " + lname + " in " + lfile);
Dianne Hackborn49237342009-08-27 20:08:01 -0700896 mSharedLibraries.put(lname, lfile);
897 }
898 XmlUtils.skipCurrentTag(parser);
899 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800900
Dianne Hackborn49237342009-08-27 20:08:01 -0700901 } else if ("feature".equals(name)) {
902 String fname = parser.getAttributeValue(null, "name");
903 if (fname == null) {
904 Log.w(TAG, "<feature> without name at "
905 + parser.getPositionDescription());
906 } else {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700907 //Log.i(TAG, "Got feature " + fname);
Dianne Hackborn49237342009-08-27 20:08:01 -0700908 FeatureInfo fi = new FeatureInfo();
909 fi.name = fname;
910 mAvailableFeatures.put(fname, fi);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 }
912 XmlUtils.skipCurrentTag(parser);
913 continue;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 } else {
916 XmlUtils.skipCurrentTag(parser);
917 continue;
918 }
919
920 }
921 } catch (XmlPullParserException e) {
922 Log.w(TAG, "Got execption parsing permissions.", e);
923 } catch (IOException e) {
924 Log.w(TAG, "Got execption parsing permissions.", e);
925 }
926 }
927
928 void readPermission(XmlPullParser parser, String name)
929 throws IOException, XmlPullParserException {
930
931 name = name.intern();
932
933 BasePermission bp = mSettings.mPermissions.get(name);
934 if (bp == null) {
935 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN);
936 mSettings.mPermissions.put(name, bp);
937 }
938 int outerDepth = parser.getDepth();
939 int type;
940 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
941 && (type != XmlPullParser.END_TAG
942 || parser.getDepth() > outerDepth)) {
943 if (type == XmlPullParser.END_TAG
944 || type == XmlPullParser.TEXT) {
945 continue;
946 }
947
948 String tagName = parser.getName();
949 if ("group".equals(tagName)) {
950 String gidStr = parser.getAttributeValue(null, "gid");
951 if (gidStr != null) {
952 int gid = Process.getGidForName(gidStr);
953 bp.gids = appendInt(bp.gids, gid);
954 } else {
955 Log.w(TAG, "<group> without gid at "
956 + parser.getPositionDescription());
957 }
958 }
959 XmlUtils.skipCurrentTag(parser);
960 }
961 }
962
963 static int[] appendInt(int[] cur, int val) {
964 if (cur == null) {
965 return new int[] { val };
966 }
967 final int N = cur.length;
968 for (int i=0; i<N; i++) {
969 if (cur[i] == val) {
970 return cur;
971 }
972 }
973 int[] ret = new int[N+1];
974 System.arraycopy(cur, 0, ret, 0, N);
975 ret[N] = val;
976 return ret;
977 }
978
979 static int[] appendInts(int[] cur, int[] add) {
980 if (add == null) return cur;
981 if (cur == null) return add;
982 final int N = add.length;
983 for (int i=0; i<N; i++) {
984 cur = appendInt(cur, add[i]);
985 }
986 return cur;
987 }
988
989 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) {
Suchi Amalapurapub897cff2009-10-14 12:11:48 -0700990 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
991 // The package has been uninstalled but has retained data and resources.
992 return PackageParser.generatePackageInfo(p, null, flags);
993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 final PackageSetting ps = (PackageSetting)p.mExtras;
995 if (ps == null) {
996 return null;
997 }
998 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
999 return PackageParser.generatePackageInfo(p, gp.gids, flags);
1000 }
1001
1002 public PackageInfo getPackageInfo(String packageName, int flags) {
1003 synchronized (mPackages) {
1004 PackageParser.Package p = mPackages.get(packageName);
1005 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001006 TAG, "getPackageInfo " + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 + ": " + p);
1008 if (p != null) {
1009 return generatePackageInfo(p, flags);
1010 }
1011 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1012 return generatePackageInfoFromSettingsLP(packageName, flags);
1013 }
1014 }
1015 return null;
1016 }
1017
1018 public int getPackageUid(String packageName) {
1019 synchronized (mPackages) {
1020 PackageParser.Package p = mPackages.get(packageName);
1021 if(p != null) {
1022 return p.applicationInfo.uid;
1023 }
1024 PackageSetting ps = mSettings.mPackages.get(packageName);
1025 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
1026 return -1;
1027 }
1028 p = ps.pkg;
1029 return p != null ? p.applicationInfo.uid : -1;
1030 }
1031 }
1032
1033 public int[] getPackageGids(String packageName) {
1034 synchronized (mPackages) {
1035 PackageParser.Package p = mPackages.get(packageName);
1036 if (Config.LOGV) Log.v(
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001037 TAG, "getPackageGids" + packageName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 + ": " + p);
1039 if (p != null) {
1040 final PackageSetting ps = (PackageSetting)p.mExtras;
1041 final SharedUserSetting suid = ps.sharedUser;
1042 return suid != null ? suid.gids : ps.gids;
1043 }
1044 }
1045 // stupid thing to indicate an error.
1046 return new int[0];
1047 }
1048
1049 public PermissionInfo getPermissionInfo(String name, int flags) {
1050 synchronized (mPackages) {
1051 final BasePermission p = mSettings.mPermissions.get(name);
1052 if (p != null && p.perm != null) {
1053 return PackageParser.generatePermissionInfo(p.perm, flags);
1054 }
1055 return null;
1056 }
1057 }
1058
1059 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) {
1060 synchronized (mPackages) {
1061 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
1062 for (BasePermission p : mSettings.mPermissions.values()) {
1063 if (group == null) {
1064 if (p.perm.info.group == null) {
1065 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1066 }
1067 } else {
1068 if (group.equals(p.perm.info.group)) {
1069 out.add(PackageParser.generatePermissionInfo(p.perm, flags));
1070 }
1071 }
1072 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 if (out.size() > 0) {
1075 return out;
1076 }
1077 return mPermissionGroups.containsKey(group) ? out : null;
1078 }
1079 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
1082 synchronized (mPackages) {
1083 return PackageParser.generatePermissionGroupInfo(
1084 mPermissionGroups.get(name), flags);
1085 }
1086 }
1087
1088 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1089 synchronized (mPackages) {
1090 final int N = mPermissionGroups.size();
1091 ArrayList<PermissionGroupInfo> out
1092 = new ArrayList<PermissionGroupInfo>(N);
1093 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) {
1094 out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
1095 }
1096 return out;
1097 }
1098 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) {
1101 PackageSetting ps = mSettings.mPackages.get(packageName);
1102 if(ps != null) {
1103 if(ps.pkg == null) {
1104 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags);
1105 if(pInfo != null) {
1106 return pInfo.applicationInfo;
1107 }
1108 return null;
1109 }
1110 return PackageParser.generateApplicationInfo(ps.pkg, flags);
1111 }
1112 return null;
1113 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) {
1116 PackageSetting ps = mSettings.mPackages.get(packageName);
1117 if(ps != null) {
1118 if(ps.pkg == null) {
1119 ps.pkg = new PackageParser.Package(packageName);
1120 ps.pkg.applicationInfo.packageName = packageName;
1121 }
1122 return generatePackageInfo(ps.pkg, flags);
1123 }
1124 return null;
1125 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 public ApplicationInfo getApplicationInfo(String packageName, int flags) {
1128 synchronized (mPackages) {
1129 PackageParser.Package p = mPackages.get(packageName);
1130 if (Config.LOGV) Log.v(
1131 TAG, "getApplicationInfo " + packageName
1132 + ": " + p);
1133 if (p != null) {
1134 // Note: isEnabledLP() does not apply here - always return info
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07001135 return PackageParser.generateApplicationInfo(p, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 }
1137 if ("android".equals(packageName)||"system".equals(packageName)) {
1138 return mAndroidApplication;
1139 }
1140 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1141 return generateApplicationInfoFromSettingsLP(packageName, flags);
1142 }
1143 }
1144 return null;
1145 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001146
1147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) {
1149 mContext.enforceCallingOrSelfPermission(
1150 android.Manifest.permission.CLEAR_APP_CACHE, null);
1151 // Queue up an async operation since clearing cache may take a little while.
1152 mHandler.post(new Runnable() {
1153 public void run() {
1154 mHandler.removeCallbacks(this);
1155 int retCode = -1;
1156 if (mInstaller != null) {
1157 retCode = mInstaller.freeCache(freeStorageSize);
1158 if (retCode < 0) {
1159 Log.w(TAG, "Couldn't clear application caches");
1160 }
1161 } //end if mInstaller
1162 if (observer != null) {
1163 try {
1164 observer.onRemoveCompleted(null, (retCode >= 0));
1165 } catch (RemoteException e) {
1166 Log.w(TAG, "RemoveException when invoking call back");
1167 }
1168 }
1169 }
1170 });
1171 }
1172
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07001173 public void freeStorage(final long freeStorageSize, final IntentSender pi) {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07001174 mContext.enforceCallingOrSelfPermission(
1175 android.Manifest.permission.CLEAR_APP_CACHE, null);
1176 // Queue up an async operation since clearing cache may take a little while.
1177 mHandler.post(new Runnable() {
1178 public void run() {
1179 mHandler.removeCallbacks(this);
1180 int retCode = -1;
1181 if (mInstaller != null) {
1182 retCode = mInstaller.freeCache(freeStorageSize);
1183 if (retCode < 0) {
1184 Log.w(TAG, "Couldn't clear application caches");
1185 }
1186 }
1187 if(pi != null) {
1188 try {
1189 // Callback via pending intent
1190 int code = (retCode >= 0) ? 1 : 0;
1191 pi.sendIntent(null, code, null,
1192 null, null);
1193 } catch (SendIntentException e1) {
1194 Log.i(TAG, "Failed to send pending intent");
1195 }
1196 }
1197 }
1198 });
1199 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 public ActivityInfo getActivityInfo(ComponentName component, int flags) {
1202 synchronized (mPackages) {
1203 PackageParser.Activity a = mActivities.mActivities.get(component);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07001204
1205 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -07001207 return PackageParser.generateActivityInfo(a, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 }
1209 if (mResolveComponentName.equals(component)) {
1210 return mResolveActivity;
1211 }
1212 }
1213 return null;
1214 }
1215
1216 public ActivityInfo getReceiverInfo(ComponentName component, int flags) {
1217 synchronized (mPackages) {
1218 PackageParser.Activity a = mReceivers.mActivities.get(component);
1219 if (Config.LOGV) Log.v(
1220 TAG, "getReceiverInfo " + component + ": " + a);
1221 if (a != null && mSettings.isEnabledLP(a.info, flags)) {
1222 return PackageParser.generateActivityInfo(a, flags);
1223 }
1224 }
1225 return null;
1226 }
1227
1228 public ServiceInfo getServiceInfo(ComponentName component, int flags) {
1229 synchronized (mPackages) {
1230 PackageParser.Service s = mServices.mServices.get(component);
1231 if (Config.LOGV) Log.v(
1232 TAG, "getServiceInfo " + component + ": " + s);
1233 if (s != null && mSettings.isEnabledLP(s.info, flags)) {
1234 return PackageParser.generateServiceInfo(s, flags);
1235 }
1236 }
1237 return null;
1238 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 public String[] getSystemSharedLibraryNames() {
1241 Set<String> libSet;
1242 synchronized (mPackages) {
1243 libSet = mSharedLibraries.keySet();
Dianne Hackborn49237342009-08-27 20:08:01 -07001244 int size = libSet.size();
1245 if (size > 0) {
1246 String[] libs = new String[size];
1247 libSet.toArray(libs);
1248 return libs;
1249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 }
Dianne Hackborn49237342009-08-27 20:08:01 -07001251 return null;
1252 }
1253
1254 public FeatureInfo[] getSystemAvailableFeatures() {
1255 Collection<FeatureInfo> featSet;
1256 synchronized (mPackages) {
1257 featSet = mAvailableFeatures.values();
1258 int size = featSet.size();
1259 if (size > 0) {
1260 FeatureInfo[] features = new FeatureInfo[size+1];
1261 featSet.toArray(features);
1262 FeatureInfo fi = new FeatureInfo();
1263 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version",
1264 FeatureInfo.GL_ES_VERSION_UNDEFINED);
1265 features[size] = fi;
1266 return features;
1267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 }
1269 return null;
1270 }
1271
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001272 public boolean hasSystemFeature(String name) {
1273 synchronized (mPackages) {
1274 return mAvailableFeatures.containsKey(name);
1275 }
1276 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 public int checkPermission(String permName, String pkgName) {
1279 synchronized (mPackages) {
1280 PackageParser.Package p = mPackages.get(pkgName);
1281 if (p != null && p.mExtras != null) {
1282 PackageSetting ps = (PackageSetting)p.mExtras;
1283 if (ps.sharedUser != null) {
1284 if (ps.sharedUser.grantedPermissions.contains(permName)) {
1285 return PackageManager.PERMISSION_GRANTED;
1286 }
1287 } else if (ps.grantedPermissions.contains(permName)) {
1288 return PackageManager.PERMISSION_GRANTED;
1289 }
1290 }
1291 }
1292 return PackageManager.PERMISSION_DENIED;
1293 }
1294
1295 public int checkUidPermission(String permName, int uid) {
1296 synchronized (mPackages) {
1297 Object obj = mSettings.getUserIdLP(uid);
1298 if (obj != null) {
1299 if (obj instanceof SharedUserSetting) {
1300 SharedUserSetting sus = (SharedUserSetting)obj;
1301 if (sus.grantedPermissions.contains(permName)) {
1302 return PackageManager.PERMISSION_GRANTED;
1303 }
1304 } else if (obj instanceof PackageSetting) {
1305 PackageSetting ps = (PackageSetting)obj;
1306 if (ps.grantedPermissions.contains(permName)) {
1307 return PackageManager.PERMISSION_GRANTED;
1308 }
1309 }
1310 } else {
1311 HashSet<String> perms = mSystemPermissions.get(uid);
1312 if (perms != null && perms.contains(permName)) {
1313 return PackageManager.PERMISSION_GRANTED;
1314 }
1315 }
1316 }
1317 return PackageManager.PERMISSION_DENIED;
1318 }
1319
1320 private BasePermission findPermissionTreeLP(String permName) {
1321 for(BasePermission bp : mSettings.mPermissionTrees.values()) {
1322 if (permName.startsWith(bp.name) &&
1323 permName.length() > bp.name.length() &&
1324 permName.charAt(bp.name.length()) == '.') {
1325 return bp;
1326 }
1327 }
1328 return null;
1329 }
1330
1331 private BasePermission checkPermissionTreeLP(String permName) {
1332 if (permName != null) {
1333 BasePermission bp = findPermissionTreeLP(permName);
1334 if (bp != null) {
1335 if (bp.uid == Binder.getCallingUid()) {
1336 return bp;
1337 }
1338 throw new SecurityException("Calling uid "
1339 + Binder.getCallingUid()
1340 + " is not allowed to add to permission tree "
1341 + bp.name + " owned by uid " + bp.uid);
1342 }
1343 }
1344 throw new SecurityException("No permission tree found for " + permName);
1345 }
1346
1347 public boolean addPermission(PermissionInfo info) {
1348 synchronized (mPackages) {
1349 if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
1350 throw new SecurityException("Label must be specified in permission");
1351 }
1352 BasePermission tree = checkPermissionTreeLP(info.name);
1353 BasePermission bp = mSettings.mPermissions.get(info.name);
1354 boolean added = bp == null;
1355 if (added) {
1356 bp = new BasePermission(info.name, tree.sourcePackage,
1357 BasePermission.TYPE_DYNAMIC);
1358 } else if (bp.type != BasePermission.TYPE_DYNAMIC) {
1359 throw new SecurityException(
1360 "Not allowed to modify non-dynamic permission "
1361 + info.name);
1362 }
1363 bp.perm = new PackageParser.Permission(tree.perm.owner,
1364 new PermissionInfo(info));
1365 bp.perm.info.packageName = tree.perm.info.packageName;
1366 bp.uid = tree.uid;
1367 if (added) {
1368 mSettings.mPermissions.put(info.name, bp);
1369 }
1370 mSettings.writeLP();
1371 return added;
1372 }
1373 }
1374
1375 public void removePermission(String name) {
1376 synchronized (mPackages) {
1377 checkPermissionTreeLP(name);
1378 BasePermission bp = mSettings.mPermissions.get(name);
1379 if (bp != null) {
1380 if (bp.type != BasePermission.TYPE_DYNAMIC) {
1381 throw new SecurityException(
1382 "Not allowed to modify non-dynamic permission "
1383 + name);
1384 }
1385 mSettings.mPermissions.remove(name);
1386 mSettings.writeLP();
1387 }
1388 }
1389 }
1390
Dianne Hackborn854060af2009-07-09 18:14:31 -07001391 public boolean isProtectedBroadcast(String actionName) {
1392 synchronized (mPackages) {
1393 return mProtectedBroadcasts.contains(actionName);
1394 }
1395 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 public int checkSignatures(String pkg1, String pkg2) {
1398 synchronized (mPackages) {
1399 PackageParser.Package p1 = mPackages.get(pkg1);
1400 PackageParser.Package p2 = mPackages.get(pkg2);
1401 if (p1 == null || p1.mExtras == null
1402 || p2 == null || p2.mExtras == null) {
1403 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1404 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001405 return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 }
1407 }
1408
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001409 public int checkUidSignatures(int uid1, int uid2) {
1410 synchronized (mPackages) {
1411 Signature[] s1;
1412 Signature[] s2;
1413 Object obj = mSettings.getUserIdLP(uid1);
1414 if (obj != null) {
1415 if (obj instanceof SharedUserSetting) {
1416 s1 = ((SharedUserSetting)obj).signatures.mSignatures;
1417 } else if (obj instanceof PackageSetting) {
1418 s1 = ((PackageSetting)obj).signatures.mSignatures;
1419 } else {
1420 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1421 }
1422 } else {
1423 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1424 }
1425 obj = mSettings.getUserIdLP(uid2);
1426 if (obj != null) {
1427 if (obj instanceof SharedUserSetting) {
1428 s2 = ((SharedUserSetting)obj).signatures.mSignatures;
1429 } else if (obj instanceof PackageSetting) {
1430 s2 = ((PackageSetting)obj).signatures.mSignatures;
1431 } else {
1432 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1433 }
1434 } else {
1435 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
1436 }
1437 return checkSignaturesLP(s1, s2);
1438 }
1439 }
1440
1441 int checkSignaturesLP(Signature[] s1, Signature[] s2) {
1442 if (s1 == null) {
1443 return s2 == null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 ? PackageManager.SIGNATURE_NEITHER_SIGNED
1445 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
1446 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001447 if (s2 == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
1449 }
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001450 final int N1 = s1.length;
1451 final int N2 = s2.length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 for (int i=0; i<N1; i++) {
1453 boolean match = false;
1454 for (int j=0; j<N2; j++) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001455 if (s1[i].equals(s2[j])) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 match = true;
1457 break;
1458 }
1459 }
1460 if (!match) {
1461 return PackageManager.SIGNATURE_NO_MATCH;
1462 }
1463 }
1464 return PackageManager.SIGNATURE_MATCH;
1465 }
1466
1467 public String[] getPackagesForUid(int uid) {
1468 synchronized (mPackages) {
1469 Object obj = mSettings.getUserIdLP(uid);
1470 if (obj instanceof SharedUserSetting) {
1471 SharedUserSetting sus = (SharedUserSetting)obj;
1472 final int N = sus.packages.size();
1473 String[] res = new String[N];
1474 Iterator<PackageSetting> it = sus.packages.iterator();
1475 int i=0;
1476 while (it.hasNext()) {
1477 res[i++] = it.next().name;
1478 }
1479 return res;
1480 } else if (obj instanceof PackageSetting) {
1481 PackageSetting ps = (PackageSetting)obj;
1482 return new String[] { ps.name };
1483 }
1484 }
1485 return null;
1486 }
1487
1488 public String getNameForUid(int uid) {
1489 synchronized (mPackages) {
1490 Object obj = mSettings.getUserIdLP(uid);
1491 if (obj instanceof SharedUserSetting) {
1492 SharedUserSetting sus = (SharedUserSetting)obj;
1493 return sus.name + ":" + sus.userId;
1494 } else if (obj instanceof PackageSetting) {
1495 PackageSetting ps = (PackageSetting)obj;
1496 return ps.name;
1497 }
1498 }
1499 return null;
1500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 public int getUidForSharedUser(String sharedUserName) {
1503 if(sharedUserName == null) {
1504 return -1;
1505 }
1506 synchronized (mPackages) {
1507 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false);
1508 if(suid == null) {
1509 return -1;
1510 }
1511 return suid.userId;
1512 }
1513 }
1514
1515 public ResolveInfo resolveIntent(Intent intent, String resolvedType,
1516 int flags) {
1517 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags);
Mihai Predaeae850c2009-05-13 10:13:48 +02001518 return chooseBestActivity(intent, resolvedType, flags, query);
1519 }
1520
Mihai Predaeae850c2009-05-13 10:13:48 +02001521 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
1522 int flags, List<ResolveInfo> query) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 if (query != null) {
1524 final int N = query.size();
1525 if (N == 1) {
1526 return query.get(0);
1527 } else if (N > 1) {
1528 // If there is more than one activity with the same priority,
1529 // then let the user decide between them.
1530 ResolveInfo r0 = query.get(0);
1531 ResolveInfo r1 = query.get(1);
1532 if (false) {
1533 System.out.println(r0.activityInfo.name +
1534 "=" + r0.priority + " vs " +
1535 r1.activityInfo.name +
1536 "=" + r1.priority);
1537 }
1538 // If the first activity has a higher priority, or a different
1539 // default, then it is always desireable to pick it.
1540 if (r0.priority != r1.priority
1541 || r0.preferredOrder != r1.preferredOrder
1542 || r0.isDefault != r1.isDefault) {
1543 return query.get(0);
1544 }
1545 // If we have saved a preference for a preferred activity for
1546 // this Intent, use that.
1547 ResolveInfo ri = findPreferredActivity(intent, resolvedType,
1548 flags, query, r0.priority);
1549 if (ri != null) {
1550 return ri;
1551 }
1552 return mResolveInfo;
1553 }
1554 }
1555 return null;
1556 }
1557
1558 ResolveInfo findPreferredActivity(Intent intent, String resolvedType,
1559 int flags, List<ResolveInfo> query, int priority) {
1560 synchronized (mPackages) {
1561 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
1562 List<PreferredActivity> prefs =
Mihai Preda074edef2009-05-18 17:13:31 +02001563 mSettings.mPreferredActivities.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
1565 if (prefs != null && prefs.size() > 0) {
1566 // First figure out how good the original match set is.
1567 // We will only allow preferred activities that came
1568 // from the same match quality.
1569 int match = 0;
1570 final int N = query.size();
1571 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match...");
1572 for (int j=0; j<N; j++) {
1573 ResolveInfo ri = query.get(j);
1574 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo
1575 + ": 0x" + Integer.toHexString(match));
1576 if (ri.match > match) match = ri.match;
1577 }
1578 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x"
1579 + Integer.toHexString(match));
1580 match &= IntentFilter.MATCH_CATEGORY_MASK;
1581 final int M = prefs.size();
1582 for (int i=0; i<M; i++) {
1583 PreferredActivity pa = prefs.get(i);
1584 if (pa.mMatch != match) {
1585 continue;
1586 }
1587 ActivityInfo ai = getActivityInfo(pa.mActivity, flags);
1588 if (DEBUG_PREFERRED) {
1589 Log.v(TAG, "Got preferred activity:");
1590 ai.dump(new LogPrinter(Log.INFO, TAG), " ");
1591 }
1592 if (ai != null) {
1593 for (int j=0; j<N; j++) {
1594 ResolveInfo ri = query.get(j);
1595 if (!ri.activityInfo.applicationInfo.packageName
1596 .equals(ai.applicationInfo.packageName)) {
1597 continue;
1598 }
1599 if (!ri.activityInfo.name.equals(ai.name)) {
1600 continue;
1601 }
1602
1603 // Okay we found a previously set preferred app.
1604 // If the result set is different from when this
1605 // was created, we need to clear it and re-ask the
1606 // user their preference.
1607 if (!pa.sameSet(query, priority)) {
1608 Log.i(TAG, "Result set changed, dropping preferred activity for "
1609 + intent + " type " + resolvedType);
1610 mSettings.mPreferredActivities.removeFilter(pa);
1611 return null;
1612 }
1613
1614 // Yay!
1615 return ri;
1616 }
1617 }
1618 }
1619 }
1620 }
1621 return null;
1622 }
1623
1624 public List<ResolveInfo> queryIntentActivities(Intent intent,
1625 String resolvedType, int flags) {
1626 ComponentName comp = intent.getComponent();
1627 if (comp != null) {
1628 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1629 ActivityInfo ai = getActivityInfo(comp, flags);
1630 if (ai != null) {
1631 ResolveInfo ri = new ResolveInfo();
1632 ri.activityInfo = ai;
1633 list.add(ri);
1634 }
1635 return list;
1636 }
1637
1638 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001639 String pkgName = intent.getPackage();
1640 if (pkgName == null) {
1641 return (List<ResolveInfo>)mActivities.queryIntent(intent,
1642 resolvedType, flags);
1643 }
1644 PackageParser.Package pkg = mPackages.get(pkgName);
1645 if (pkg != null) {
1646 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
1647 resolvedType, flags, pkg.activities);
1648 }
1649 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 }
1651 }
1652
1653 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
1654 Intent[] specifics, String[] specificTypes, Intent intent,
1655 String resolvedType, int flags) {
1656 final String resultsAction = intent.getAction();
1657
1658 List<ResolveInfo> results = queryIntentActivities(
1659 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER);
1660 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results);
1661
1662 int specificsPos = 0;
1663 int N;
1664
1665 // todo: note that the algorithm used here is O(N^2). This
1666 // isn't a problem in our current environment, but if we start running
1667 // into situations where we have more than 5 or 10 matches then this
1668 // should probably be changed to something smarter...
1669
1670 // First we go through and resolve each of the specific items
1671 // that were supplied, taking care of removing any corresponding
1672 // duplicate items in the generic resolve list.
1673 if (specifics != null) {
1674 for (int i=0; i<specifics.length; i++) {
1675 final Intent sintent = specifics[i];
1676 if (sintent == null) {
1677 continue;
1678 }
1679
1680 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent);
1681 String action = sintent.getAction();
1682 if (resultsAction != null && resultsAction.equals(action)) {
1683 // If this action was explicitly requested, then don't
1684 // remove things that have it.
1685 action = null;
1686 }
1687 ComponentName comp = sintent.getComponent();
1688 ResolveInfo ri = null;
1689 ActivityInfo ai = null;
1690 if (comp == null) {
1691 ri = resolveIntent(
1692 sintent,
1693 specificTypes != null ? specificTypes[i] : null,
1694 flags);
1695 if (ri == null) {
1696 continue;
1697 }
1698 if (ri == mResolveInfo) {
1699 // ACK! Must do something better with this.
1700 }
1701 ai = ri.activityInfo;
1702 comp = new ComponentName(ai.applicationInfo.packageName,
1703 ai.name);
1704 } else {
1705 ai = getActivityInfo(comp, flags);
1706 if (ai == null) {
1707 continue;
1708 }
1709 }
1710
1711 // Look for any generic query activities that are duplicates
1712 // of this specific one, and remove them from the results.
1713 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai);
1714 N = results.size();
1715 int j;
1716 for (j=specificsPos; j<N; j++) {
1717 ResolveInfo sri = results.get(j);
1718 if ((sri.activityInfo.name.equals(comp.getClassName())
1719 && sri.activityInfo.applicationInfo.packageName.equals(
1720 comp.getPackageName()))
1721 || (action != null && sri.filter.matchAction(action))) {
1722 results.remove(j);
1723 if (Config.LOGV) Log.v(
1724 TAG, "Removing duplicate item from " + j
1725 + " due to specific " + specificsPos);
1726 if (ri == null) {
1727 ri = sri;
1728 }
1729 j--;
1730 N--;
1731 }
1732 }
1733
1734 // Add this specific item to its proper place.
1735 if (ri == null) {
1736 ri = new ResolveInfo();
1737 ri.activityInfo = ai;
1738 }
1739 results.add(specificsPos, ri);
1740 ri.specificIndex = i;
1741 specificsPos++;
1742 }
1743 }
1744
1745 // Now we go through the remaining generic results and remove any
1746 // duplicate actions that are found here.
1747 N = results.size();
1748 for (int i=specificsPos; i<N-1; i++) {
1749 final ResolveInfo rii = results.get(i);
1750 if (rii.filter == null) {
1751 continue;
1752 }
1753
1754 // Iterate over all of the actions of this result's intent
1755 // filter... typically this should be just one.
1756 final Iterator<String> it = rii.filter.actionsIterator();
1757 if (it == null) {
1758 continue;
1759 }
1760 while (it.hasNext()) {
1761 final String action = it.next();
1762 if (resultsAction != null && resultsAction.equals(action)) {
1763 // If this action was explicitly requested, then don't
1764 // remove things that have it.
1765 continue;
1766 }
1767 for (int j=i+1; j<N; j++) {
1768 final ResolveInfo rij = results.get(j);
1769 if (rij.filter != null && rij.filter.hasAction(action)) {
1770 results.remove(j);
1771 if (Config.LOGV) Log.v(
1772 TAG, "Removing duplicate item from " + j
1773 + " due to action " + action + " at " + i);
1774 j--;
1775 N--;
1776 }
1777 }
1778 }
1779
1780 // If the caller didn't request filter information, drop it now
1781 // so we don't have to marshall/unmarshall it.
1782 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1783 rii.filter = null;
1784 }
1785 }
1786
1787 // Filter out the caller activity if so requested.
1788 if (caller != null) {
1789 N = results.size();
1790 for (int i=0; i<N; i++) {
1791 ActivityInfo ainfo = results.get(i).activityInfo;
1792 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName)
1793 && caller.getClassName().equals(ainfo.name)) {
1794 results.remove(i);
1795 break;
1796 }
1797 }
1798 }
1799
1800 // If the caller didn't request filter information,
1801 // drop them now so we don't have to
1802 // marshall/unmarshall it.
1803 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) {
1804 N = results.size();
1805 for (int i=0; i<N; i++) {
1806 results.get(i).filter = null;
1807 }
1808 }
1809
1810 if (Config.LOGV) Log.v(TAG, "Result: " + results);
1811 return results;
1812 }
1813
1814 public List<ResolveInfo> queryIntentReceivers(Intent intent,
1815 String resolvedType, int flags) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001816 ComponentName comp = intent.getComponent();
1817 if (comp != null) {
1818 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1819 ActivityInfo ai = getReceiverInfo(comp, flags);
1820 if (ai != null) {
1821 ResolveInfo ri = new ResolveInfo();
1822 ri.activityInfo = ai;
1823 list.add(ri);
1824 }
1825 return list;
1826 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001829 String pkgName = intent.getPackage();
1830 if (pkgName == null) {
1831 return (List<ResolveInfo>)mReceivers.queryIntent(intent,
1832 resolvedType, flags);
1833 }
1834 PackageParser.Package pkg = mPackages.get(pkgName);
1835 if (pkg != null) {
1836 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent,
1837 resolvedType, flags, pkg.receivers);
1838 }
1839 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 }
1841 }
1842
1843 public ResolveInfo resolveService(Intent intent, String resolvedType,
1844 int flags) {
1845 List<ResolveInfo> query = queryIntentServices(intent, resolvedType,
1846 flags);
1847 if (query != null) {
1848 if (query.size() >= 1) {
1849 // If there is more than one service with the same priority,
1850 // just arbitrarily pick the first one.
1851 return query.get(0);
1852 }
1853 }
1854 return null;
1855 }
1856
1857 public List<ResolveInfo> queryIntentServices(Intent intent,
1858 String resolvedType, int flags) {
1859 ComponentName comp = intent.getComponent();
1860 if (comp != null) {
1861 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
1862 ServiceInfo si = getServiceInfo(comp, flags);
1863 if (si != null) {
1864 ResolveInfo ri = new ResolveInfo();
1865 ri.serviceInfo = si;
1866 list.add(ri);
1867 }
1868 return list;
1869 }
1870
1871 synchronized (mPackages) {
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07001872 String pkgName = intent.getPackage();
1873 if (pkgName == null) {
1874 return (List<ResolveInfo>)mServices.queryIntent(intent,
1875 resolvedType, flags);
1876 }
1877 PackageParser.Package pkg = mPackages.get(pkgName);
1878 if (pkg != null) {
1879 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent,
1880 resolvedType, flags, pkg.services);
1881 }
1882 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 }
1884 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 public List<PackageInfo> getInstalledPackages(int flags) {
1887 ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
1888
1889 synchronized (mPackages) {
1890 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1891 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1892 while (i.hasNext()) {
1893 final PackageSetting ps = i.next();
1894 PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
1895 if(psPkg != null) {
1896 finalList.add(psPkg);
1897 }
1898 }
1899 }
1900 else {
1901 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1902 while (i.hasNext()) {
1903 final PackageParser.Package p = i.next();
1904 if (p.applicationInfo != null) {
1905 PackageInfo pi = generatePackageInfo(p, flags);
1906 if(pi != null) {
1907 finalList.add(pi);
1908 }
1909 }
1910 }
1911 }
1912 }
1913 return finalList;
1914 }
1915
1916 public List<ApplicationInfo> getInstalledApplications(int flags) {
1917 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1918 synchronized(mPackages) {
1919 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
1920 Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
1921 while (i.hasNext()) {
1922 final PackageSetting ps = i.next();
1923 ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
1924 if(ai != null) {
1925 finalList.add(ai);
1926 }
1927 }
1928 }
1929 else {
1930 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1931 while (i.hasNext()) {
1932 final PackageParser.Package p = i.next();
1933 if (p.applicationInfo != null) {
1934 ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
1935 if(ai != null) {
1936 finalList.add(ai);
1937 }
1938 }
1939 }
1940 }
1941 }
1942 return finalList;
1943 }
1944
1945 public List<ApplicationInfo> getPersistentApplications(int flags) {
1946 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
1947
1948 synchronized (mPackages) {
1949 Iterator<PackageParser.Package> i = mPackages.values().iterator();
1950 while (i.hasNext()) {
1951 PackageParser.Package p = i.next();
1952 if (p.applicationInfo != null
1953 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
1954 && (!mSafeMode || (p.applicationInfo.flags
1955 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1956 finalList.add(p.applicationInfo);
1957 }
1958 }
1959 }
1960
1961 return finalList;
1962 }
1963
1964 public ProviderInfo resolveContentProvider(String name, int flags) {
1965 synchronized (mPackages) {
1966 final PackageParser.Provider provider = mProviders.get(name);
1967 return provider != null
1968 && mSettings.isEnabledLP(provider.info, flags)
1969 && (!mSafeMode || (provider.info.applicationInfo.flags
1970 &ApplicationInfo.FLAG_SYSTEM) != 0)
1971 ? PackageParser.generateProviderInfo(provider, flags)
1972 : null;
1973 }
1974 }
1975
Fred Quintana718d8a22009-04-29 17:53:20 -07001976 /**
1977 * @deprecated
1978 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 public void querySyncProviders(List outNames, List outInfo) {
1980 synchronized (mPackages) {
1981 Iterator<Map.Entry<String, PackageParser.Provider>> i
1982 = mProviders.entrySet().iterator();
1983
1984 while (i.hasNext()) {
1985 Map.Entry<String, PackageParser.Provider> entry = i.next();
1986 PackageParser.Provider p = entry.getValue();
1987
1988 if (p.syncable
1989 && (!mSafeMode || (p.info.applicationInfo.flags
1990 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
1991 outNames.add(entry.getKey());
1992 outInfo.add(PackageParser.generateProviderInfo(p, 0));
1993 }
1994 }
1995 }
1996 }
1997
1998 public List<ProviderInfo> queryContentProviders(String processName,
1999 int uid, int flags) {
2000 ArrayList<ProviderInfo> finalList = null;
2001
2002 synchronized (mPackages) {
2003 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
2004 while (i.hasNext()) {
2005 PackageParser.Provider p = i.next();
2006 if (p.info.authority != null
2007 && (processName == null ||
2008 (p.info.processName.equals(processName)
2009 && p.info.applicationInfo.uid == uid))
2010 && mSettings.isEnabledLP(p.info, flags)
2011 && (!mSafeMode || (p.info.applicationInfo.flags
2012 &ApplicationInfo.FLAG_SYSTEM) != 0)) {
2013 if (finalList == null) {
2014 finalList = new ArrayList<ProviderInfo>(3);
2015 }
2016 finalList.add(PackageParser.generateProviderInfo(p,
2017 flags));
2018 }
2019 }
2020 }
2021
2022 if (finalList != null) {
2023 Collections.sort(finalList, mProviderInitOrderSorter);
2024 }
2025
2026 return finalList;
2027 }
2028
2029 public InstrumentationInfo getInstrumentationInfo(ComponentName name,
2030 int flags) {
2031 synchronized (mPackages) {
2032 final PackageParser.Instrumentation i = mInstrumentation.get(name);
2033 return PackageParser.generateInstrumentationInfo(i, flags);
2034 }
2035 }
2036
2037 public List<InstrumentationInfo> queryInstrumentation(String targetPackage,
2038 int flags) {
2039 ArrayList<InstrumentationInfo> finalList =
2040 new ArrayList<InstrumentationInfo>();
2041
2042 synchronized (mPackages) {
2043 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator();
2044 while (i.hasNext()) {
2045 PackageParser.Instrumentation p = i.next();
2046 if (targetPackage == null
2047 || targetPackage.equals(p.info.targetPackage)) {
2048 finalList.add(PackageParser.generateInstrumentationInfo(p,
2049 flags));
2050 }
2051 }
2052 }
2053
2054 return finalList;
2055 }
2056
2057 private void scanDirLI(File dir, int flags, int scanMode) {
2058 Log.d(TAG, "Scanning app dir " + dir);
2059
2060 String[] files = dir.list();
2061
2062 int i;
2063 for (i=0; i<files.length; i++) {
2064 File file = new File(dir, files[i]);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002065 PackageParser.Package pkg = scanPackageLI(file,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
2067 }
2068 }
2069
2070 private static void reportSettingsProblem(int priority, String msg) {
2071 try {
2072 File dataDir = Environment.getDataDirectory();
2073 File systemDir = new File(dataDir, "system");
2074 File fname = new File(systemDir, "uiderrors.txt");
2075 FileOutputStream out = new FileOutputStream(fname, true);
2076 PrintWriter pw = new PrintWriter(out);
2077 pw.println(msg);
2078 pw.close();
2079 FileUtils.setPermissions(
2080 fname.toString(),
2081 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH,
2082 -1, -1);
2083 } catch (java.io.IOException e) {
2084 }
2085 Log.println(priority, TAG, msg);
2086 }
2087
2088 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
2089 PackageParser.Package pkg, File srcFile, int parseFlags) {
2090 if (GET_CERTIFICATES) {
2091 if (ps == null || !ps.codePath.equals(srcFile)
2092 || ps.getTimeStamp() != srcFile.lastModified()) {
2093 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
2094 if (!pp.collectCertificates(pkg, parseFlags)) {
2095 mLastScanError = pp.getParseError();
2096 return false;
2097 }
2098 }
2099 }
2100 return true;
2101 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 /*
2104 * Scan a package and return the newly parsed package.
2105 * Returns null in case of errors and the error code is stored in mLastScanError
2106 */
2107 private PackageParser.Package scanPackageLI(File scanFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002108 int parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 int scanMode) {
2110 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002111 String scanPath = scanFile.getPath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 parseFlags |= mDefParseFlags;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002113 PackageParser pp = new PackageParser(scanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002115 final PackageParser.Package pkg = pp.parsePackage(scanFile,
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002116 scanPath,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002117 mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 if (pkg == null) {
2119 mLastScanError = pp.getParseError();
2120 return null;
2121 }
2122 PackageSetting ps;
2123 PackageSetting updatedPkg;
2124 synchronized (mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002125 ps = mSettings.peekPackageLP(pkg.packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
2127 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002128 // Verify certificates first
2129 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
2130 Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
2131 return null;
2132 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 if (updatedPkg != null) {
2134 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
2135 parseFlags |= PackageParser.PARSE_IS_SYSTEM;
2136 }
2137 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2138 // Check for updated system applications here
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002139 if ((ps != null) && (!ps.codePath.equals(scanFile))) {
2140 if (pkg.mVersionCode < ps.versionCode) {
2141 // The system package has been updated and the code path does not match
2142 // Ignore entry. Just return
2143 Log.w(TAG, "Package:" + pkg.packageName +
2144 " has been updated. Ignoring the one from path:"+scanFile);
2145 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2146 return null;
2147 } else {
2148 // Delete the older apk pointed to by ps
2149 // At this point, its safely assumed that package installation for
2150 // apps in system partition will go through. If not there won't be a working
2151 // version of the app
2152 synchronized (mPackages) {
2153 // Just remove the loaded entries from package lists.
2154 mPackages.remove(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002155 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002156 InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
2157 args.cleanUpResourcesLI();
Dianne Hackborna33e3f72009-09-29 17:28:24 -07002158 mSettings.enableSystemPackageLP(ps.name);
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07002159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 }
2161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 // The apk is forward locked (not public) if its code and resources
2163 // are kept in different files.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002164 // TODO grab this value from PackageSettings
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002166 parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
Suchi Amalapurapuf2c10722009-07-29 17:19:39 -07002167 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002168
2169 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
2170 if (ps != null && ps.resourcePathString != null) {
2171 pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
2172 } else {
2173 // Should not happen at all. Just log an error.
2174 Log.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
2175 }
2176 } else {
2177 pkg.applicationInfo.publicSourceDir = pkg.mScanPath;
2178 }
2179 pkg.applicationInfo.sourceDir = pkg.mScanPath;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 // Note that we invoke the following method only if we are about to unpack an application
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002181 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 }
2183
2184 private static String fixProcessName(String defProcessName,
2185 String processName, int uid) {
2186 if (processName == null) {
2187 return defProcessName;
2188 }
2189 return processName;
2190 }
2191
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002192 private boolean verifySignaturesLP(PackageSetting pkgSetting,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 PackageParser.Package pkg, int parseFlags, boolean updateSignature) {
2194 if (pkg.mSignatures != null) {
2195 if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures,
2196 updateSignature)) {
2197 Log.e(TAG, "Package " + pkg.packageName
2198 + " signatures do not match the previously installed version; ignoring!");
2199 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2200 return false;
2201 }
2202
2203 if (pkgSetting.sharedUser != null) {
2204 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2205 pkg.mSignatures, updateSignature)) {
2206 Log.e(TAG, "Package " + pkg.packageName
2207 + " has no signatures that match those in shared user "
2208 + pkgSetting.sharedUser.name + "; ignoring!");
2209 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
2210 return false;
2211 }
2212 }
2213 } else {
2214 pkg.mSignatures = pkgSetting.signatures.mSignatures;
2215 }
2216 return true;
2217 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002218
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002219 public boolean performDexOpt(String packageName) {
2220 if (!mNoDexOpt) {
2221 return false;
2222 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002223
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002224 PackageParser.Package p;
2225 synchronized (mPackages) {
2226 p = mPackages.get(packageName);
2227 if (p == null || p.mDidDexOpt) {
2228 return false;
2229 }
2230 }
2231 synchronized (mInstallLock) {
2232 return performDexOptLI(p, false) == DEX_OPT_PERFORMED;
2233 }
2234 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002235
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002236 static final int DEX_OPT_SKIPPED = 0;
2237 static final int DEX_OPT_PERFORMED = 1;
2238 static final int DEX_OPT_FAILED = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002239
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002240 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) {
2241 boolean performed = false;
Marco Nelissend595c792009-07-02 15:23:26 -07002242 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) {
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002243 String path = pkg.mScanPath;
2244 int ret = 0;
2245 try {
2246 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002247 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002248 !isForwardLocked(pkg));
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002249 pkg.mDidDexOpt = true;
2250 performed = true;
2251 }
2252 } catch (FileNotFoundException e) {
2253 Log.w(TAG, "Apk not found for dexopt: " + path);
2254 ret = -1;
2255 } catch (IOException e) {
2256 Log.w(TAG, "Exception reading apk: " + path, e);
2257 ret = -1;
2258 }
2259 if (ret < 0) {
2260 //error from installer
2261 return DEX_OPT_FAILED;
2262 }
2263 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002264
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002265 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
2266 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08002267
2268 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
2269 return Environment.isEncryptedFilesystemEnabled() &&
2270 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
2271 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 private PackageParser.Package scanPackageLI(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 PackageParser.Package pkg, int parseFlags, int scanMode) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002275 File scanFile = new File(pkg.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002276 mScanningPath = scanFile;
2277 if (pkg == null) {
2278 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
2279 return null;
2280 }
2281
2282 final String pkgName = pkg.applicationInfo.packageName;
2283 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2284 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2285 }
2286
2287 if (pkgName.equals("android")) {
2288 synchronized (mPackages) {
2289 if (mAndroidApplication != null) {
2290 Log.w(TAG, "*************************************************");
2291 Log.w(TAG, "Core android package being redefined. Skipping.");
2292 Log.w(TAG, " file=" + mScanningPath);
2293 Log.w(TAG, "*************************************************");
2294 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2295 return null;
2296 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 // Set up information for our fall-back user intent resolution
2299 // activity.
2300 mPlatformPackage = pkg;
2301 pkg.mVersionCode = mSdkVersion;
2302 mAndroidApplication = pkg.applicationInfo;
2303 mResolveActivity.applicationInfo = mAndroidApplication;
2304 mResolveActivity.name = ResolverActivity.class.getName();
2305 mResolveActivity.packageName = mAndroidApplication.packageName;
2306 mResolveActivity.processName = mAndroidApplication.processName;
2307 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
2308 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
2309 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
2310 mResolveActivity.exported = true;
2311 mResolveActivity.enabled = true;
2312 mResolveInfo.activityInfo = mResolveActivity;
2313 mResolveInfo.priority = 0;
2314 mResolveInfo.preferredOrder = 0;
2315 mResolveInfo.match = 0;
2316 mResolveComponentName = new ComponentName(
2317 mAndroidApplication.packageName, mResolveActivity.name);
2318 }
2319 }
2320
2321 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
2322 TAG, "Scanning package " + pkgName);
2323 if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
2324 Log.w(TAG, "*************************************************");
2325 Log.w(TAG, "Application package " + pkgName
2326 + " already installed. Skipping duplicate.");
2327 Log.w(TAG, "*************************************************");
2328 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
2329 return null;
2330 }
2331
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002332 // Initialize package source and resource directories
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002333 File destCodeFile = new File(pkg.applicationInfo.sourceDir);
2334 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 SharedUserSetting suid = null;
2337 PackageSetting pkgSetting = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002339 boolean removeExisting = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341 synchronized (mPackages) {
2342 // Check all shared libraries and map to their actual file path.
Dianne Hackborn49237342009-08-27 20:08:01 -07002343 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
2344 if (mTmpSharedLibraries == null ||
2345 mTmpSharedLibraries.length < mSharedLibraries.size()) {
2346 mTmpSharedLibraries = new String[mSharedLibraries.size()];
2347 }
2348 int num = 0;
2349 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
2350 for (int i=0; i<N; i++) {
2351 String file = mSharedLibraries.get(pkg.usesLibraries.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 if (file == null) {
2353 Log.e(TAG, "Package " + pkg.packageName
2354 + " requires unavailable shared library "
Dianne Hackborn49237342009-08-27 20:08:01 -07002355 + pkg.usesLibraries.get(i) + "; failing!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
2357 return null;
2358 }
Dianne Hackborn49237342009-08-27 20:08:01 -07002359 mTmpSharedLibraries[num] = file;
2360 num++;
2361 }
2362 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
2363 for (int i=0; i<N; i++) {
2364 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
2365 if (file == null) {
2366 Log.w(TAG, "Package " + pkg.packageName
2367 + " desires unavailable shared library "
2368 + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
2369 } else {
2370 mTmpSharedLibraries[num] = file;
2371 num++;
2372 }
2373 }
2374 if (num > 0) {
2375 pkg.usesLibraryFiles = new String[num];
2376 System.arraycopy(mTmpSharedLibraries, 0,
2377 pkg.usesLibraryFiles, 0, num);
2378 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002379
Dianne Hackborn49237342009-08-27 20:08:01 -07002380 if (pkg.reqFeatures != null) {
2381 N = pkg.reqFeatures.size();
2382 for (int i=0; i<N; i++) {
2383 FeatureInfo fi = pkg.reqFeatures.get(i);
2384 if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
2385 // Don't care.
2386 continue;
2387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002388
Dianne Hackborn49237342009-08-27 20:08:01 -07002389 if (fi.name != null) {
2390 if (mAvailableFeatures.get(fi.name) == null) {
2391 Log.e(TAG, "Package " + pkg.packageName
2392 + " requires unavailable feature "
2393 + fi.name + "; failing!");
2394 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
2395 return null;
2396 }
2397 }
2398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 if (pkg.mSharedUserId != null) {
2403 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
2404 pkg.applicationInfo.flags, true);
2405 if (suid == null) {
2406 Log.w(TAG, "Creating application package " + pkgName
2407 + " for shared user failed");
2408 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2409 return null;
2410 }
2411 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
2412 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
2413 + suid.userId + "): packages=" + suid.packages);
2414 }
2415 }
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002416
2417 // Just create the setting, don't add it yet. For already existing packages
2418 // the PkgSetting exists already and doesn't have to be created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
2420 destResourceFile, pkg.applicationInfo.flags, true, false);
2421 if (pkgSetting == null) {
2422 Log.w(TAG, "Creating application package " + pkgName + " failed");
2423 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2424 return null;
2425 }
2426 if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
2427 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
2428 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002430 pkg.applicationInfo.uid = pkgSetting.userId;
2431 pkg.mExtras = pkgSetting;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002432
2433 if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434 (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
2435 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
2436 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
2437 return null;
2438 }
2439 // The signature has changed, but this package is in the system
2440 // image... let's recover!
Suchi Amalapurapuc4dd60f2009-03-24 21:10:53 -07002441 pkgSetting.signatures.mSignatures = pkg.mSignatures;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 // However... if this package is part of a shared user, but it
2443 // doesn't match the signature of the shared user, let's fail.
2444 // What this means is that you can't change the signatures
2445 // associated with an overall shared user, which doesn't seem all
2446 // that unreasonable.
2447 if (pkgSetting.sharedUser != null) {
2448 if (!pkgSetting.sharedUser.signatures.mergeSignatures(
2449 pkg.mSignatures, false)) {
2450 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
2451 return null;
2452 }
2453 }
2454 removeExisting = true;
2455 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002456
The Android Open Source Project10592532009-03-18 17:39:46 -07002457 // Verify that this new package doesn't have any content providers
2458 // that conflict with existing packages. Only do this if the
2459 // package isn't already installed, since we don't want to break
2460 // things that are installed.
2461 if ((scanMode&SCAN_NEW_INSTALL) != 0) {
2462 int N = pkg.providers.size();
2463 int i;
2464 for (i=0; i<N; i++) {
2465 PackageParser.Provider p = pkg.providers.get(i);
2466 String names[] = p.info.authority.split(";");
2467 for (int j = 0; j < names.length; j++) {
2468 if (mProviders.containsKey(names[j])) {
2469 PackageParser.Provider other = mProviders.get(names[j]);
2470 Log.w(TAG, "Can't install because provider name " + names[j] +
2471 " (in package " + pkg.applicationInfo.packageName +
2472 ") is already used by "
2473 + ((other != null && other.component != null)
2474 ? other.component.getPackageName() : "?"));
2475 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
2476 return null;
2477 }
2478 }
2479 }
2480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 }
2482
2483 if (removeExisting) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002484 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002485 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002486 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 if (ret != 0) {
2488 String msg = "System package " + pkg.packageName
2489 + " could not have data directory erased after signature change.";
2490 reportSettingsProblem(Log.WARN, msg);
2491 mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
2492 return null;
2493 }
2494 }
2495 Log.w(TAG, "System package " + pkg.packageName
2496 + " signature changed: existing data removed.");
2497 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
2498 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 long scanFileTime = scanFile.lastModified();
2501 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
2502 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
2503 pkg.applicationInfo.processName = fixProcessName(
2504 pkg.applicationInfo.packageName,
2505 pkg.applicationInfo.processName,
2506 pkg.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507
2508 File dataPath;
2509 if (mPlatformPackage == pkg) {
2510 // The system package is special.
2511 dataPath = new File (Environment.getDataDirectory(), "system");
2512 pkg.applicationInfo.dataDir = dataPath.getPath();
2513 } else {
2514 // This is a normal package, need to make its data directory.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002515 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
2516 if (useEncryptedFSDir) {
2517 dataPath = new File(mSecureAppDataDir, pkgName);
2518 } else {
2519 dataPath = new File(mAppDataDir, pkgName);
2520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 if (dataPath.exists()) {
2522 mOutPermissions[1] = 0;
2523 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
2524 if (mOutPermissions[1] == pkg.applicationInfo.uid
2525 || !Process.supportsProcesses()) {
2526 pkg.applicationInfo.dataDir = dataPath.getPath();
2527 } else {
2528 boolean recovered = false;
2529 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
2530 // If this is a system app, we can at least delete its
2531 // current data so the application will still work.
2532 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002533 int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002534 if(ret >= 0) {
2535 // Old data gone!
2536 String msg = "System package " + pkg.packageName
2537 + " has changed from uid: "
2538 + mOutPermissions[1] + " to "
2539 + pkg.applicationInfo.uid + "; old data erased";
2540 reportSettingsProblem(Log.WARN, msg);
2541 recovered = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 // And now re-install the app.
Oscar Montemayora8529f62009-11-18 10:14:20 -08002544 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 pkg.applicationInfo.uid);
2546 if (ret == -1) {
2547 // Ack should not happen!
2548 msg = "System package " + pkg.packageName
2549 + " could not have data directory re-created after delete.";
2550 reportSettingsProblem(Log.WARN, msg);
2551 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2552 return null;
2553 }
2554 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 if (!recovered) {
2557 mHasSystemUidErrors = true;
2558 }
2559 }
2560 if (!recovered) {
2561 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
2562 + pkg.applicationInfo.uid + "/fs_"
2563 + mOutPermissions[1];
2564 String msg = "Package " + pkg.packageName
2565 + " has mismatched uid: "
2566 + mOutPermissions[1] + " on disk, "
2567 + pkg.applicationInfo.uid + " in settings";
2568 synchronized (mPackages) {
2569 if (!mReportedUidError) {
2570 mReportedUidError = true;
2571 msg = msg + "; read messages:\n"
2572 + mSettings.getReadMessagesLP();
2573 }
2574 reportSettingsProblem(Log.ERROR, msg);
2575 }
2576 }
2577 }
2578 pkg.applicationInfo.dataDir = dataPath.getPath();
2579 } else {
2580 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
2581 Log.v(TAG, "Want this data dir: " + dataPath);
2582 //invoke installer to do the actual installation
2583 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08002584 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002585 pkg.applicationInfo.uid);
2586 if(ret < 0) {
2587 // Error from installer
2588 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
2589 return null;
2590 }
2591 } else {
2592 dataPath.mkdirs();
2593 if (dataPath.exists()) {
2594 FileUtils.setPermissions(
2595 dataPath.toString(),
2596 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2597 pkg.applicationInfo.uid, pkg.applicationInfo.uid);
2598 }
2599 }
2600 if (dataPath.exists()) {
2601 pkg.applicationInfo.dataDir = dataPath.getPath();
2602 } else {
2603 Log.w(TAG, "Unable to create data directory: " + dataPath);
2604 pkg.applicationInfo.dataDir = null;
2605 }
2606 }
2607 }
2608
2609 // Perform shared library installation and dex validation and
2610 // optimization, if this is not a system app.
2611 if (mInstaller != null) {
2612 String path = scanFile.getPath();
2613 if (scanFileNewer) {
2614 Log.i(TAG, path + " changed; unpacking");
Dianne Hackbornb1811182009-05-21 15:45:42 -07002615 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
2616 if (err != PackageManager.INSTALL_SUCCEEDED) {
2617 mLastScanError = err;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 return null;
2619 }
2620 }
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002621 pkg.mScanPath = path;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002622
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -07002623 if ((scanMode&SCAN_NO_DEX) == 0) {
2624 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002625 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
2626 return null;
2627 }
2628 }
2629 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 if (mFactoryTest && pkg.requestedPermissions.contains(
2632 android.Manifest.permission.FACTORY_TEST)) {
2633 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
2634 }
2635
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002636 // We don't expect installation to fail beyond this point,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002637 if ((scanMode&SCAN_MONITOR) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 mAppDirs.put(pkg.mPath, pkg);
2639 }
2640
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002641 // Request the ActivityManager to kill the process(only for existing packages)
2642 // so that we do not end up in a confused state while the user is still using the older
2643 // version of the application while the new one gets installed.
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002644 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0) {
2645 killApplication(pkg.applicationInfo.packageName,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002646 pkg.applicationInfo.uid);
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07002647 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 // Add the new setting to mSettings
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08002651 mSettings.insertPackageSettingLP(pkgSetting, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002652 // Add the new setting to mPackages
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07002653 mPackages.put(pkg.applicationInfo.packageName, pkg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002654 int N = pkg.providers.size();
2655 StringBuilder r = null;
2656 int i;
2657 for (i=0; i<N; i++) {
2658 PackageParser.Provider p = pkg.providers.get(i);
2659 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
2660 p.info.processName, pkg.applicationInfo.uid);
2661 mProvidersByComponent.put(new ComponentName(p.info.packageName,
2662 p.info.name), p);
2663 p.syncable = p.info.isSyncable;
2664 String names[] = p.info.authority.split(";");
2665 p.info.authority = null;
2666 for (int j = 0; j < names.length; j++) {
2667 if (j == 1 && p.syncable) {
2668 // We only want the first authority for a provider to possibly be
2669 // syncable, so if we already added this provider using a different
2670 // authority clear the syncable flag. We copy the provider before
2671 // changing it because the mProviders object contains a reference
2672 // to a provider that we don't want to change.
2673 // Only do this for the second authority since the resulting provider
2674 // object can be the same for all future authorities for this provider.
2675 p = new PackageParser.Provider(p);
2676 p.syncable = false;
2677 }
2678 if (!mProviders.containsKey(names[j])) {
2679 mProviders.put(names[j], p);
2680 if (p.info.authority == null) {
2681 p.info.authority = names[j];
2682 } else {
2683 p.info.authority = p.info.authority + ";" + names[j];
2684 }
2685 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
2686 Log.d(TAG, "Registered content provider: " + names[j] +
2687 ", className = " + p.info.name +
2688 ", isSyncable = " + p.info.isSyncable);
2689 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07002690 PackageParser.Provider other = mProviders.get(names[j]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 Log.w(TAG, "Skipping provider name " + names[j] +
2692 " (in package " + pkg.applicationInfo.packageName +
The Android Open Source Project10592532009-03-18 17:39:46 -07002693 "): name already used by "
2694 + ((other != null && other.component != null)
2695 ? other.component.getPackageName() : "?"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 }
2697 }
2698 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2699 if (r == null) {
2700 r = new StringBuilder(256);
2701 } else {
2702 r.append(' ');
2703 }
2704 r.append(p.info.name);
2705 }
2706 }
2707 if (r != null) {
2708 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
2709 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002711 N = pkg.services.size();
2712 r = null;
2713 for (i=0; i<N; i++) {
2714 PackageParser.Service s = pkg.services.get(i);
2715 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
2716 s.info.processName, pkg.applicationInfo.uid);
2717 mServices.addService(s);
2718 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2719 if (r == null) {
2720 r = new StringBuilder(256);
2721 } else {
2722 r.append(' ');
2723 }
2724 r.append(s.info.name);
2725 }
2726 }
2727 if (r != null) {
2728 if (Config.LOGD) Log.d(TAG, " Services: " + r);
2729 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002731 N = pkg.receivers.size();
2732 r = null;
2733 for (i=0; i<N; i++) {
2734 PackageParser.Activity a = pkg.receivers.get(i);
2735 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2736 a.info.processName, pkg.applicationInfo.uid);
2737 mReceivers.addActivity(a, "receiver");
2738 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2739 if (r == null) {
2740 r = new StringBuilder(256);
2741 } else {
2742 r.append(' ');
2743 }
2744 r.append(a.info.name);
2745 }
2746 }
2747 if (r != null) {
2748 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
2749 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 N = pkg.activities.size();
2752 r = null;
2753 for (i=0; i<N; i++) {
2754 PackageParser.Activity a = pkg.activities.get(i);
2755 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
2756 a.info.processName, pkg.applicationInfo.uid);
2757 mActivities.addActivity(a, "activity");
2758 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2759 if (r == null) {
2760 r = new StringBuilder(256);
2761 } else {
2762 r.append(' ');
2763 }
2764 r.append(a.info.name);
2765 }
2766 }
2767 if (r != null) {
2768 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
2769 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002771 N = pkg.permissionGroups.size();
2772 r = null;
2773 for (i=0; i<N; i++) {
2774 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
2775 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
2776 if (cur == null) {
2777 mPermissionGroups.put(pg.info.name, pg);
2778 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2779 if (r == null) {
2780 r = new StringBuilder(256);
2781 } else {
2782 r.append(' ');
2783 }
2784 r.append(pg.info.name);
2785 }
2786 } else {
2787 Log.w(TAG, "Permission group " + pg.info.name + " from package "
2788 + pg.info.packageName + " ignored: original from "
2789 + cur.info.packageName);
2790 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2791 if (r == null) {
2792 r = new StringBuilder(256);
2793 } else {
2794 r.append(' ');
2795 }
2796 r.append("DUP:");
2797 r.append(pg.info.name);
2798 }
2799 }
2800 }
2801 if (r != null) {
2802 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r);
2803 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 N = pkg.permissions.size();
2806 r = null;
2807 for (i=0; i<N; i++) {
2808 PackageParser.Permission p = pkg.permissions.get(i);
2809 HashMap<String, BasePermission> permissionMap =
2810 p.tree ? mSettings.mPermissionTrees
2811 : mSettings.mPermissions;
2812 p.group = mPermissionGroups.get(p.info.group);
2813 if (p.info.group == null || p.group != null) {
2814 BasePermission bp = permissionMap.get(p.info.name);
2815 if (bp == null) {
2816 bp = new BasePermission(p.info.name, p.info.packageName,
2817 BasePermission.TYPE_NORMAL);
2818 permissionMap.put(p.info.name, bp);
2819 }
2820 if (bp.perm == null) {
2821 if (bp.sourcePackage == null
2822 || bp.sourcePackage.equals(p.info.packageName)) {
2823 BasePermission tree = findPermissionTreeLP(p.info.name);
2824 if (tree == null
2825 || tree.sourcePackage.equals(p.info.packageName)) {
2826 bp.perm = p;
2827 bp.uid = pkg.applicationInfo.uid;
2828 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2829 if (r == null) {
2830 r = new StringBuilder(256);
2831 } else {
2832 r.append(' ');
2833 }
2834 r.append(p.info.name);
2835 }
2836 } else {
2837 Log.w(TAG, "Permission " + p.info.name + " from package "
2838 + p.info.packageName + " ignored: base tree "
2839 + tree.name + " is from package "
2840 + tree.sourcePackage);
2841 }
2842 } else {
2843 Log.w(TAG, "Permission " + p.info.name + " from package "
2844 + p.info.packageName + " ignored: original from "
2845 + bp.sourcePackage);
2846 }
2847 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2848 if (r == null) {
2849 r = new StringBuilder(256);
2850 } else {
2851 r.append(' ');
2852 }
2853 r.append("DUP:");
2854 r.append(p.info.name);
2855 }
2856 } else {
2857 Log.w(TAG, "Permission " + p.info.name + " from package "
2858 + p.info.packageName + " ignored: no group "
2859 + p.group);
2860 }
2861 }
2862 if (r != null) {
2863 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
2864 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 N = pkg.instrumentation.size();
2867 r = null;
2868 for (i=0; i<N; i++) {
2869 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
2870 a.info.packageName = pkg.applicationInfo.packageName;
2871 a.info.sourceDir = pkg.applicationInfo.sourceDir;
2872 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
2873 a.info.dataDir = pkg.applicationInfo.dataDir;
2874 mInstrumentation.put(a.component, a);
2875 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
2876 if (r == null) {
2877 r = new StringBuilder(256);
2878 } else {
2879 r.append(' ');
2880 }
2881 r.append(a.info.name);
2882 }
2883 }
2884 if (r != null) {
2885 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
2886 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002887
Dianne Hackborn854060af2009-07-09 18:14:31 -07002888 if (pkg.protectedBroadcasts != null) {
2889 N = pkg.protectedBroadcasts.size();
2890 for (i=0; i<N; i++) {
2891 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
2892 }
2893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 pkgSetting.setTimeStamp(scanFileTime);
2896 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 return pkg;
2899 }
2900
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08002901 private void killApplication(String pkgName, int uid) {
2902 // Request the ActivityManager to kill the process(only for existing packages)
2903 // so that we do not end up in a confused state while the user is still using the older
2904 // version of the application while the new one gets installed.
2905 IActivityManager am = ActivityManagerNative.getDefault();
2906 if (am != null) {
2907 try {
2908 am.killApplicationWithUid(pkgName, uid);
2909 } catch (RemoteException e) {
2910 }
2911 }
2912 }
2913
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002914 // The following constants are returned by cachePackageSharedLibsForAbiLI
2915 // to indicate if native shared libraries were found in the package.
2916 // Values are:
2917 // PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
2918 // PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
2919 // PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
2920 // in package (and not installed)
2921 //
2922 private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
2923 private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
2924 private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002926 // Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
2927 // and automatically copy them to /data/data/<appname>/lib if present.
2928 //
2929 // NOTE: this method may throw an IOException if the library cannot
2930 // be copied to its final destination, e.g. if there isn't enough
2931 // room left on the data partition, or a ZipException if the package
2932 // file is malformed.
2933 //
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08002934 private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
2935 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002936 File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
2937 final String apkLib = "lib/";
2938 final int apkLibLen = apkLib.length();
2939 final int cpuAbiLen = cpuAbi.length();
2940 final String libPrefix = "lib";
2941 final int libPrefixLen = libPrefix.length();
2942 final String libSuffix = ".so";
2943 final int libSuffixLen = libSuffix.length();
2944 boolean hasNativeLibraries = false;
2945 boolean installedNativeLibraries = false;
2946
2947 // the minimum length of a valid native shared library of the form
2948 // lib/<something>/lib<name>.so.
2949 final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
2950
2951 ZipFile zipFile = new ZipFile(scanFile);
2952 Enumeration<ZipEntry> entries =
2953 (Enumeration<ZipEntry>) zipFile.entries();
2954
2955 while (entries.hasMoreElements()) {
2956 ZipEntry entry = entries.nextElement();
2957 // skip directories
2958 if (entry.isDirectory()) {
2959 continue;
2960 }
2961 String entryName = entry.getName();
2962
2963 // check that the entry looks like lib/<something>/lib<name>.so
2964 // here, but don't check the ABI just yet.
2965 //
2966 // - must be sufficiently long
2967 // - must end with libSuffix, i.e. ".so"
2968 // - must start with apkLib, i.e. "lib/"
2969 if (entryName.length() < minEntryLen ||
2970 !entryName.endsWith(libSuffix) ||
2971 !entryName.startsWith(apkLib) ) {
2972 continue;
2973 }
2974
2975 // file name must start with libPrefix, i.e. "lib"
2976 int lastSlash = entryName.lastIndexOf('/');
2977
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002978 if (lastSlash < 0 ||
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08002979 !entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
2980 continue;
2981 }
2982
2983 hasNativeLibraries = true;
2984
2985 // check the cpuAbi now, between lib/ and /lib<name>.so
2986 //
2987 if (lastSlash != apkLibLen + cpuAbiLen ||
2988 !entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
2989 continue;
2990
2991 // extract the library file name, ensure it doesn't contain
2992 // weird characters. we're guaranteed here that it doesn't contain
2993 // a directory separator though.
2994 String libFileName = entryName.substring(lastSlash+1);
2995 if (!FileUtils.isFilenameSafe(new File(libFileName))) {
2996 continue;
2997 }
2998
2999 installedNativeLibraries = true;
3000
3001 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
3002 File.separator + libFileName;
3003 File sharedLibraryFile = new File(sharedLibraryFilePath);
3004 if (! sharedLibraryFile.exists() ||
3005 sharedLibraryFile.length() != entry.getSize() ||
3006 sharedLibraryFile.lastModified() != entry.getTime()) {
3007 if (Config.LOGD) {
3008 Log.d(TAG, "Caching shared lib " + entry.getName());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003010 if (mInstaller == null) {
3011 sharedLibraryDir.mkdir();
Dianne Hackbornb1811182009-05-21 15:45:42 -07003012 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003013 cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003014 sharedLibraryFile);
3015 }
3016 }
3017 if (!hasNativeLibraries)
3018 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3019
3020 if (!installedNativeLibraries)
3021 return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
3022
3023 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3024 }
3025
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003026 // Find the gdbserver executable program in a package at
3027 // lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
3028 //
3029 // Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
3030 // or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
3031 //
3032 private int cachePackageGdbServerLI(PackageParser.Package pkg,
3033 File dataPath, File scanFile, String cpuAbi) throws IOException, ZipException {
3034 File installGdbServerDir = new File(dataPath.getPath() + "/lib");
3035 final String GDBSERVER = "gdbserver";
3036 final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
3037
3038 ZipFile zipFile = new ZipFile(scanFile);
3039 Enumeration<ZipEntry> entries =
3040 (Enumeration<ZipEntry>) zipFile.entries();
3041
3042 while (entries.hasMoreElements()) {
3043 ZipEntry entry = entries.nextElement();
3044 // skip directories
3045 if (entry.isDirectory()) {
3046 continue;
3047 }
3048 String entryName = entry.getName();
3049
3050 if (!entryName.equals(apkGdbServerPath)) {
3051 continue;
3052 }
3053
3054 String installGdbServerPath = installGdbServerDir.getPath() +
3055 "/" + GDBSERVER;
3056 File installGdbServerFile = new File(installGdbServerPath);
3057 if (! installGdbServerFile.exists() ||
3058 installGdbServerFile.length() != entry.getSize() ||
3059 installGdbServerFile.lastModified() != entry.getTime()) {
3060 if (Config.LOGD) {
3061 Log.d(TAG, "Caching gdbserver " + entry.getName());
3062 }
3063 if (mInstaller == null) {
3064 installGdbServerDir.mkdir();
3065 }
3066 cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
3067 installGdbServerFile);
3068 }
3069 return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
3070 }
3071 return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
3072 }
3073
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003074 // extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
3075 // and copy them to /data/data/<appname>/lib.
3076 //
3077 // This function will first try the main CPU ABI defined by Build.CPU_ABI
3078 // (which corresponds to ro.product.cpu.abi), and also try an alternate
3079 // one if ro.product.cpu.abi2 is defined.
3080 //
3081 private int cachePackageSharedLibsLI(PackageParser.Package pkg,
3082 File dataPath, File scanFile) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003083 String cpuAbi = Build.CPU_ABI;
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003084 try {
3085 int result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi);
3086
3087 // some architectures are capable of supporting several CPU ABIs
3088 // for example, 'armeabi-v7a' also supports 'armeabi' native code
3089 // this is indicated by the definition of the ro.product.cpu.abi2
3090 // system property.
3091 //
3092 // only scan the package twice in case of ABI mismatch
3093 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003094 final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003095 if (cpuAbi2 != null) {
3096 result = cachePackageSharedLibsForAbiLI(pkg, dataPath, scanFile, cpuAbi2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003098
3099 if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
3100 Log.w(TAG,"Native ABI mismatch from package file");
3101 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 }
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003103
3104 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3105 cpuAbi = cpuAbi2;
3106 }
3107 }
3108
3109 // for debuggable packages, also extract gdbserver from lib/<abi>
3110 // into /data/data/<appname>/lib too.
3111 if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
3112 (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
3113 int result2 = cachePackageGdbServerLI(pkg, dataPath, scanFile, cpuAbi);
3114 if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
3115 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
3116 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003117 }
David 'Digit' Turnerfeba7432009-11-06 17:54:12 -08003118 } catch (ZipException e) {
3119 Log.w(TAG, "Failed to extract data from package file", e);
3120 return PackageManager.INSTALL_FAILED_INVALID_APK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 } catch (IOException e) {
Dianne Hackbornb1811182009-05-21 15:45:42 -07003122 Log.w(TAG, "Failed to cache package shared libs", e);
3123 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 }
Dianne Hackbornb1811182009-05-21 15:45:42 -07003125 return PackageManager.INSTALL_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 }
3127
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003128 private void cacheNativeBinaryLI(PackageParser.Package pkg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003129 ZipFile zipFile, ZipEntry entry,
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003130 File binaryDir,
3131 File binaryFile) throws IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 InputStream inputStream = zipFile.getInputStream(entry);
3133 try {
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003134 File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 String tempFilePath = tempFile.getPath();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003136 // XXX package manager can't change owner, so the executable files for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 // now need to be left as world readable and owned by the system.
3138 if (! FileUtils.copyToFile(inputStream, tempFile) ||
3139 ! tempFile.setLastModified(entry.getTime()) ||
3140 FileUtils.setPermissions(tempFilePath,
3141 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003142 |FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003143 |FileUtils.S_IROTH, -1, -1) != 0 ||
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003144 ! tempFile.renameTo(binaryFile)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 // Failed to properly write file.
3146 tempFile.delete();
David 'Digit' Turner1edab2b2010-01-21 15:15:23 -08003147 throw new IOException("Couldn't create cached binary "
3148 + binaryFile + " in " + binaryDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 }
3150 } finally {
3151 inputStream.close();
3152 }
3153 }
3154
3155 void removePackageLI(PackageParser.Package pkg, boolean chatty) {
3156 if (chatty && Config.LOGD) Log.d(
3157 TAG, "Removing package " + pkg.applicationInfo.packageName );
3158
3159 synchronized (mPackages) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 clearPackagePreferredActivitiesLP(pkg.packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003162 mPackages.remove(pkg.applicationInfo.packageName);
3163 if (pkg.mPath != null) {
3164 mAppDirs.remove(pkg.mPath);
3165 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167 PackageSetting ps = (PackageSetting)pkg.mExtras;
3168 if (ps != null && ps.sharedUser != null) {
3169 // XXX don't do this until the data is removed.
3170 if (false) {
3171 ps.sharedUser.packages.remove(ps);
3172 if (ps.sharedUser.packages.size() == 0) {
3173 // Remove.
3174 }
3175 }
3176 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 int N = pkg.providers.size();
3179 StringBuilder r = null;
3180 int i;
3181 for (i=0; i<N; i++) {
3182 PackageParser.Provider p = pkg.providers.get(i);
3183 mProvidersByComponent.remove(new ComponentName(p.info.packageName,
3184 p.info.name));
3185 if (p.info.authority == null) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003187 /* The is another ContentProvider with this authority when
3188 * this app was installed so this authority is null,
3189 * Ignore it as we don't have to unregister the provider.
3190 */
3191 continue;
3192 }
3193 String names[] = p.info.authority.split(";");
3194 for (int j = 0; j < names.length; j++) {
3195 if (mProviders.get(names[j]) == p) {
3196 mProviders.remove(names[j]);
3197 if (chatty && Config.LOGD) Log.d(
3198 TAG, "Unregistered content provider: " + names[j] +
3199 ", className = " + p.info.name +
3200 ", isSyncable = " + p.info.isSyncable);
3201 }
3202 }
3203 if (chatty) {
3204 if (r == null) {
3205 r = new StringBuilder(256);
3206 } else {
3207 r.append(' ');
3208 }
3209 r.append(p.info.name);
3210 }
3211 }
3212 if (r != null) {
3213 if (Config.LOGD) Log.d(TAG, " Providers: " + r);
3214 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 N = pkg.services.size();
3217 r = null;
3218 for (i=0; i<N; i++) {
3219 PackageParser.Service s = pkg.services.get(i);
3220 mServices.removeService(s);
3221 if (chatty) {
3222 if (r == null) {
3223 r = new StringBuilder(256);
3224 } else {
3225 r.append(' ');
3226 }
3227 r.append(s.info.name);
3228 }
3229 }
3230 if (r != null) {
3231 if (Config.LOGD) Log.d(TAG, " Services: " + r);
3232 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003234 N = pkg.receivers.size();
3235 r = null;
3236 for (i=0; i<N; i++) {
3237 PackageParser.Activity a = pkg.receivers.get(i);
3238 mReceivers.removeActivity(a, "receiver");
3239 if (chatty) {
3240 if (r == null) {
3241 r = new StringBuilder(256);
3242 } else {
3243 r.append(' ');
3244 }
3245 r.append(a.info.name);
3246 }
3247 }
3248 if (r != null) {
3249 if (Config.LOGD) Log.d(TAG, " Receivers: " + r);
3250 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003252 N = pkg.activities.size();
3253 r = null;
3254 for (i=0; i<N; i++) {
3255 PackageParser.Activity a = pkg.activities.get(i);
3256 mActivities.removeActivity(a, "activity");
3257 if (chatty) {
3258 if (r == null) {
3259 r = new StringBuilder(256);
3260 } else {
3261 r.append(' ');
3262 }
3263 r.append(a.info.name);
3264 }
3265 }
3266 if (r != null) {
3267 if (Config.LOGD) Log.d(TAG, " Activities: " + r);
3268 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 N = pkg.permissions.size();
3271 r = null;
3272 for (i=0; i<N; i++) {
3273 PackageParser.Permission p = pkg.permissions.get(i);
3274 boolean tree = false;
3275 BasePermission bp = mSettings.mPermissions.get(p.info.name);
3276 if (bp == null) {
3277 tree = true;
3278 bp = mSettings.mPermissionTrees.get(p.info.name);
3279 }
3280 if (bp != null && bp.perm == p) {
3281 if (bp.type != BasePermission.TYPE_BUILTIN) {
3282 if (tree) {
3283 mSettings.mPermissionTrees.remove(p.info.name);
3284 } else {
3285 mSettings.mPermissions.remove(p.info.name);
3286 }
3287 } else {
3288 bp.perm = null;
3289 }
3290 if (chatty) {
3291 if (r == null) {
3292 r = new StringBuilder(256);
3293 } else {
3294 r.append(' ');
3295 }
3296 r.append(p.info.name);
3297 }
3298 }
3299 }
3300 if (r != null) {
3301 if (Config.LOGD) Log.d(TAG, " Permissions: " + r);
3302 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 N = pkg.instrumentation.size();
3305 r = null;
3306 for (i=0; i<N; i++) {
3307 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
3308 mInstrumentation.remove(a.component);
3309 if (chatty) {
3310 if (r == null) {
3311 r = new StringBuilder(256);
3312 } else {
3313 r.append(' ');
3314 }
3315 r.append(a.info.name);
3316 }
3317 }
3318 if (r != null) {
3319 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r);
3320 }
3321 }
3322 }
3323
3324 private static final boolean isPackageFilename(String name) {
3325 return name != null && name.endsWith(".apk");
3326 }
3327
3328 private void updatePermissionsLP() {
3329 // Make sure there are no dangling permission trees.
3330 Iterator<BasePermission> it = mSettings.mPermissionTrees
3331 .values().iterator();
3332 while (it.hasNext()) {
3333 BasePermission bp = it.next();
3334 if (bp.perm == null) {
3335 Log.w(TAG, "Removing dangling permission tree: " + bp.name
3336 + " from package " + bp.sourcePackage);
3337 it.remove();
3338 }
3339 }
3340
3341 // Make sure all dynamic permissions have been assigned to a package,
3342 // and make sure there are no dangling permissions.
3343 it = mSettings.mPermissions.values().iterator();
3344 while (it.hasNext()) {
3345 BasePermission bp = it.next();
3346 if (bp.type == BasePermission.TYPE_DYNAMIC) {
3347 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
3348 + bp.name + " pkg=" + bp.sourcePackage
3349 + " info=" + bp.pendingInfo);
3350 if (bp.perm == null && bp.pendingInfo != null) {
3351 BasePermission tree = findPermissionTreeLP(bp.name);
3352 if (tree != null) {
3353 bp.perm = new PackageParser.Permission(tree.perm.owner,
3354 new PermissionInfo(bp.pendingInfo));
3355 bp.perm.info.packageName = tree.perm.info.packageName;
3356 bp.perm.info.name = bp.name;
3357 bp.uid = tree.uid;
3358 }
3359 }
3360 }
3361 if (bp.perm == null) {
3362 Log.w(TAG, "Removing dangling permission: " + bp.name
3363 + " from package " + bp.sourcePackage);
3364 it.remove();
3365 }
3366 }
3367
3368 // Now update the permissions for all packages, in particular
3369 // replace the granted permissions of the system packages.
3370 for (PackageParser.Package pkg : mPackages.values()) {
3371 grantPermissionsLP(pkg, false);
3372 }
3373 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
3376 final PackageSetting ps = (PackageSetting)pkg.mExtras;
3377 if (ps == null) {
3378 return;
3379 }
3380 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;
3381 boolean addedPermission = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 if (replace) {
3384 ps.permissionsFixed = false;
3385 if (gp == ps) {
3386 gp.grantedPermissions.clear();
3387 gp.gids = mGlobalGids;
3388 }
3389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 if (gp.gids == null) {
3392 gp.gids = mGlobalGids;
3393 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 final int N = pkg.requestedPermissions.size();
3396 for (int i=0; i<N; i++) {
3397 String name = pkg.requestedPermissions.get(i);
3398 BasePermission bp = mSettings.mPermissions.get(name);
3399 PackageParser.Permission p = bp != null ? bp.perm : null;
3400 if (false) {
3401 if (gp != ps) {
3402 Log.i(TAG, "Package " + pkg.packageName + " checking " + name
3403 + ": " + p);
3404 }
3405 }
3406 if (p != null) {
3407 final String perm = p.info.name;
3408 boolean allowed;
3409 if (p.info.protectionLevel == PermissionInfo.PROTECTION_NORMAL
3410 || p.info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
3411 allowed = true;
3412 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
3413 || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003414 allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003415 == PackageManager.SIGNATURE_MATCH)
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07003416 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 == PackageManager.SIGNATURE_MATCH);
3418 if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
3419 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
3420 // For updated system applications, the signatureOrSystem permission
3421 // is granted only if it had been defined by the original application.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003422 if ((pkg.applicationInfo.flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003423 & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
3424 PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
3425 if(sysPs.grantedPermissions.contains(perm)) {
3426 allowed = true;
3427 } else {
3428 allowed = false;
3429 }
3430 } else {
3431 allowed = true;
3432 }
3433 }
3434 }
3435 } else {
3436 allowed = false;
3437 }
3438 if (false) {
3439 if (gp != ps) {
3440 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm);
3441 }
3442 }
3443 if (allowed) {
3444 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
3445 && ps.permissionsFixed) {
3446 // If this is an existing, non-system package, then
3447 // we can't add any new permissions to it.
3448 if (!gp.loadedPermissions.contains(perm)) {
3449 allowed = false;
Dianne Hackborn62da8462009-05-13 15:06:13 -07003450 // Except... if this is a permission that was added
3451 // to the platform (note: need to only do this when
3452 // updating the platform).
3453 final int NP = PackageParser.NEW_PERMISSIONS.length;
3454 for (int ip=0; ip<NP; ip++) {
3455 final PackageParser.NewPermissionInfo npi
3456 = PackageParser.NEW_PERMISSIONS[ip];
3457 if (npi.name.equals(perm)
3458 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) {
3459 allowed = true;
San Mehat5a3a77d2009-06-01 09:25:28 -07003460 Log.i(TAG, "Auto-granting WRITE_EXTERNAL_STORAGE to old pkg "
Dianne Hackborn62da8462009-05-13 15:06:13 -07003461 + pkg.packageName);
3462 break;
3463 }
3464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003465 }
3466 }
3467 if (allowed) {
3468 if (!gp.grantedPermissions.contains(perm)) {
3469 addedPermission = true;
3470 gp.grantedPermissions.add(perm);
3471 gp.gids = appendInts(gp.gids, bp.gids);
3472 }
3473 } else {
3474 Log.w(TAG, "Not granting permission " + perm
3475 + " to package " + pkg.packageName
3476 + " because it was previously installed without");
3477 }
3478 } else {
3479 Log.w(TAG, "Not granting permission " + perm
3480 + " to package " + pkg.packageName
3481 + " (protectionLevel=" + p.info.protectionLevel
3482 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags)
3483 + ")");
3484 }
3485 } else {
3486 Log.w(TAG, "Unknown permission " + name
3487 + " in package " + pkg.packageName);
3488 }
3489 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003491 if ((addedPermission || replace) && !ps.permissionsFixed &&
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07003492 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
3493 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003494 // This is the first that we have heard about this package, so the
3495 // permissions we have now selected are fixed until explicitly
3496 // changed.
3497 ps.permissionsFixed = true;
3498 gp.loadedPermissions = new HashSet<String>(gp.grantedPermissions);
3499 }
3500 }
3501
3502 private final class ActivityIntentResolver
3503 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003504 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003505 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003506 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 }
3508
Mihai Preda074edef2009-05-18 17:13:31 +02003509 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003510 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003511 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003512 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3513 }
3514
Mihai Predaeae850c2009-05-13 10:13:48 +02003515 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3516 ArrayList<PackageParser.Activity> packageActivities) {
3517 if (packageActivities == null) {
3518 return null;
3519 }
3520 mFlags = flags;
3521 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3522 int N = packageActivities.size();
3523 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut =
3524 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N);
Mihai Predac3320db2009-05-18 20:15:32 +02003525
3526 ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
Mihai Predaeae850c2009-05-13 10:13:48 +02003527 for (int i = 0; i < N; ++i) {
Mihai Predac3320db2009-05-18 20:15:32 +02003528 intentFilters = packageActivities.get(i).intents;
3529 if (intentFilters != null && intentFilters.size() > 0) {
3530 listCut.add(intentFilters);
3531 }
Mihai Predaeae850c2009-05-13 10:13:48 +02003532 }
3533 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3534 }
3535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 public final void addActivity(PackageParser.Activity a, String type) {
3537 mActivities.put(a.component, a);
3538 if (SHOW_INFO || Config.LOGV) Log.v(
3539 TAG, " " + type + " " +
3540 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3541 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3542 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003543 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3545 if (SHOW_INFO || Config.LOGV) {
3546 Log.v(TAG, " IntentFilter:");
3547 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3548 }
3549 if (!intent.debugCheck()) {
3550 Log.w(TAG, "==> For Activity " + a.info.name);
3551 }
3552 addFilter(intent);
3553 }
3554 }
3555
3556 public final void removeActivity(PackageParser.Activity a, String type) {
3557 mActivities.remove(a.component);
3558 if (SHOW_INFO || Config.LOGV) Log.v(
3559 TAG, " " + type + " " +
3560 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
3561 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name);
3562 int NI = a.intents.size();
Mihai Predaeae850c2009-05-13 10:13:48 +02003563 for (int j=0; j<NI; j++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
3565 if (SHOW_INFO || Config.LOGV) {
3566 Log.v(TAG, " IntentFilter:");
3567 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3568 }
3569 removeFilter(intent);
3570 }
3571 }
3572
3573 @Override
3574 protected boolean allowFilterResult(
3575 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
3576 ActivityInfo filterAi = filter.activity.info;
3577 for (int i=dest.size()-1; i>=0; i--) {
3578 ActivityInfo destAi = dest.get(i).activityInfo;
3579 if (destAi.name == filterAi.name
3580 && destAi.packageName == filterAi.packageName) {
3581 return false;
3582 }
3583 }
3584 return true;
3585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 @Override
3588 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
3589 int match) {
3590 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) {
3591 return null;
3592 }
3593 final PackageParser.Activity activity = info.activity;
3594 if (mSafeMode && (activity.info.applicationInfo.flags
3595 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3596 return null;
3597 }
3598 final ResolveInfo res = new ResolveInfo();
3599 res.activityInfo = PackageParser.generateActivityInfo(activity,
3600 mFlags);
3601 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3602 res.filter = info;
3603 }
3604 res.priority = info.getPriority();
3605 res.preferredOrder = activity.owner.mPreferredOrder;
3606 //System.out.println("Result: " + res.activityInfo.className +
3607 // " = " + res.priority);
3608 res.match = match;
3609 res.isDefault = info.hasDefault;
3610 res.labelRes = info.labelRes;
3611 res.nonLocalizedLabel = info.nonLocalizedLabel;
3612 res.icon = info.icon;
3613 return res;
3614 }
3615
3616 @Override
3617 protected void sortResults(List<ResolveInfo> results) {
3618 Collections.sort(results, mResolvePrioritySorter);
3619 }
3620
3621 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003622 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003623 PackageParser.ActivityIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003624 out.print(prefix); out.print(
3625 Integer.toHexString(System.identityHashCode(filter.activity)));
3626 out.print(' ');
3627 out.println(filter.activity.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 }
3629
3630// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3631// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3632// final List<ResolveInfo> retList = Lists.newArrayList();
3633// while (i.hasNext()) {
3634// final ResolveInfo resolveInfo = i.next();
3635// if (isEnabledLP(resolveInfo.activityInfo)) {
3636// retList.add(resolveInfo);
3637// }
3638// }
3639// return retList;
3640// }
3641
3642 // Keys are String (activity class name), values are Activity.
3643 private final HashMap<ComponentName, PackageParser.Activity> mActivities
3644 = new HashMap<ComponentName, PackageParser.Activity>();
3645 private int mFlags;
3646 }
3647
3648 private final class ServiceIntentResolver
3649 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
Mihai Preda074edef2009-05-18 17:13:31 +02003650 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
Mihai Preda074edef2009-05-18 17:13:31 +02003652 return super.queryIntent(intent, resolvedType, defaultOnly);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003653 }
3654
Mihai Preda074edef2009-05-18 17:13:31 +02003655 public List queryIntent(Intent intent, String resolvedType, int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 mFlags = flags;
Mihai Preda074edef2009-05-18 17:13:31 +02003657 return super.queryIntent(intent, resolvedType,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0);
3659 }
3660
Dianne Hackbornc14b9ccd2009-06-17 18:02:12 -07003661 public List queryIntentForPackage(Intent intent, String resolvedType, int flags,
3662 ArrayList<PackageParser.Service> packageServices) {
3663 if (packageServices == null) {
3664 return null;
3665 }
3666 mFlags = flags;
3667 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
3668 int N = packageServices.size();
3669 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut =
3670 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N);
3671
3672 ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
3673 for (int i = 0; i < N; ++i) {
3674 intentFilters = packageServices.get(i).intents;
3675 if (intentFilters != null && intentFilters.size() > 0) {
3676 listCut.add(intentFilters);
3677 }
3678 }
3679 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut);
3680 }
3681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 public final void addService(PackageParser.Service s) {
3683 mServices.put(s.component, s);
3684 if (SHOW_INFO || Config.LOGV) Log.v(
3685 TAG, " " + (s.info.nonLocalizedLabel != null
3686 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3687 if (SHOW_INFO || Config.LOGV) Log.v(
3688 TAG, " Class=" + s.info.name);
3689 int NI = s.intents.size();
3690 int j;
3691 for (j=0; j<NI; j++) {
3692 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3693 if (SHOW_INFO || Config.LOGV) {
3694 Log.v(TAG, " IntentFilter:");
3695 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3696 }
3697 if (!intent.debugCheck()) {
3698 Log.w(TAG, "==> For Service " + s.info.name);
3699 }
3700 addFilter(intent);
3701 }
3702 }
3703
3704 public final void removeService(PackageParser.Service s) {
3705 mServices.remove(s.component);
3706 if (SHOW_INFO || Config.LOGV) Log.v(
3707 TAG, " " + (s.info.nonLocalizedLabel != null
3708 ? s.info.nonLocalizedLabel : s.info.name) + ":");
3709 if (SHOW_INFO || Config.LOGV) Log.v(
3710 TAG, " Class=" + s.info.name);
3711 int NI = s.intents.size();
3712 int j;
3713 for (j=0; j<NI; j++) {
3714 PackageParser.ServiceIntentInfo intent = s.intents.get(j);
3715 if (SHOW_INFO || Config.LOGV) {
3716 Log.v(TAG, " IntentFilter:");
3717 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
3718 }
3719 removeFilter(intent);
3720 }
3721 }
3722
3723 @Override
3724 protected boolean allowFilterResult(
3725 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
3726 ServiceInfo filterSi = filter.service.info;
3727 for (int i=dest.size()-1; i>=0; i--) {
3728 ServiceInfo destAi = dest.get(i).serviceInfo;
3729 if (destAi.name == filterSi.name
3730 && destAi.packageName == filterSi.packageName) {
3731 return false;
3732 }
3733 }
3734 return true;
3735 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 @Override
3738 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
3739 int match) {
3740 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
3741 if (!mSettings.isEnabledLP(info.service.info, mFlags)) {
3742 return null;
3743 }
3744 final PackageParser.Service service = info.service;
3745 if (mSafeMode && (service.info.applicationInfo.flags
3746 &ApplicationInfo.FLAG_SYSTEM) == 0) {
3747 return null;
3748 }
3749 final ResolveInfo res = new ResolveInfo();
3750 res.serviceInfo = PackageParser.generateServiceInfo(service,
3751 mFlags);
3752 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
3753 res.filter = filter;
3754 }
3755 res.priority = info.getPriority();
3756 res.preferredOrder = service.owner.mPreferredOrder;
3757 //System.out.println("Result: " + res.activityInfo.className +
3758 // " = " + res.priority);
3759 res.match = match;
3760 res.isDefault = info.hasDefault;
3761 res.labelRes = info.labelRes;
3762 res.nonLocalizedLabel = info.nonLocalizedLabel;
3763 res.icon = info.icon;
3764 return res;
3765 }
3766
3767 @Override
3768 protected void sortResults(List<ResolveInfo> results) {
3769 Collections.sort(results, mResolvePrioritySorter);
3770 }
3771
3772 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003773 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003774 PackageParser.ServiceIntentInfo filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07003775 out.print(prefix); out.print(
3776 Integer.toHexString(System.identityHashCode(filter.service)));
3777 out.print(' ');
3778 out.println(filter.service.componentShortName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 }
3780
3781// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
3782// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
3783// final List<ResolveInfo> retList = Lists.newArrayList();
3784// while (i.hasNext()) {
3785// final ResolveInfo resolveInfo = (ResolveInfo) i;
3786// if (isEnabledLP(resolveInfo.serviceInfo)) {
3787// retList.add(resolveInfo);
3788// }
3789// }
3790// return retList;
3791// }
3792
3793 // Keys are String (activity class name), values are Activity.
3794 private final HashMap<ComponentName, PackageParser.Service> mServices
3795 = new HashMap<ComponentName, PackageParser.Service>();
3796 private int mFlags;
3797 };
3798
3799 private static final Comparator<ResolveInfo> mResolvePrioritySorter =
3800 new Comparator<ResolveInfo>() {
3801 public int compare(ResolveInfo r1, ResolveInfo r2) {
3802 int v1 = r1.priority;
3803 int v2 = r2.priority;
3804 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
3805 if (v1 != v2) {
3806 return (v1 > v2) ? -1 : 1;
3807 }
3808 v1 = r1.preferredOrder;
3809 v2 = r2.preferredOrder;
3810 if (v1 != v2) {
3811 return (v1 > v2) ? -1 : 1;
3812 }
3813 if (r1.isDefault != r2.isDefault) {
3814 return r1.isDefault ? -1 : 1;
3815 }
3816 v1 = r1.match;
3817 v2 = r2.match;
3818 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
3819 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3820 }
3821 };
3822
3823 private static final Comparator<ProviderInfo> mProviderInitOrderSorter =
3824 new Comparator<ProviderInfo>() {
3825 public int compare(ProviderInfo p1, ProviderInfo p2) {
3826 final int v1 = p1.initOrder;
3827 final int v2 = p2.initOrder;
3828 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
3829 }
3830 };
3831
3832 private static final void sendPackageBroadcast(String action, String pkg, Bundle extras) {
3833 IActivityManager am = ActivityManagerNative.getDefault();
3834 if (am != null) {
3835 try {
3836 final Intent intent = new Intent(action,
3837 pkg != null ? Uri.fromParts("package", pkg, null) : null);
3838 if (extras != null) {
3839 intent.putExtras(extras);
3840 }
Dianne Hackbornde7faf62009-06-30 13:27:30 -07003841 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003842 am.broadcastIntent(
3843 null, intent,
3844 null, null, 0, null, null, null, false, false);
3845 } catch (RemoteException ex) {
3846 }
3847 }
3848 }
3849
3850 private final class AppDirObserver extends FileObserver {
3851 public AppDirObserver(String path, int mask, boolean isrom) {
3852 super(path, mask);
3853 mRootDir = path;
3854 mIsRom = isrom;
3855 }
3856
3857 public void onEvent(int event, String path) {
3858 String removedPackage = null;
3859 int removedUid = -1;
3860 String addedPackage = null;
3861 int addedUid = -1;
3862
3863 synchronized (mInstallLock) {
3864 String fullPathStr = null;
3865 File fullPath = null;
3866 if (path != null) {
3867 fullPath = new File(mRootDir, path);
3868 fullPathStr = fullPath.getPath();
3869 }
3870
3871 if (Config.LOGV) Log.v(
3872 TAG, "File " + fullPathStr + " changed: "
3873 + Integer.toHexString(event));
3874
3875 if (!isPackageFilename(path)) {
3876 if (Config.LOGV) Log.v(
3877 TAG, "Ignoring change of non-package file: " + fullPathStr);
3878 return;
3879 }
3880
3881 if ((event&REMOVE_EVENTS) != 0) {
3882 synchronized (mInstallLock) {
3883 PackageParser.Package p = mAppDirs.get(fullPathStr);
3884 if (p != null) {
3885 removePackageLI(p, true);
3886 removedPackage = p.applicationInfo.packageName;
3887 removedUid = p.applicationInfo.uid;
3888 }
3889 }
3890 }
3891
3892 if ((event&ADD_EVENTS) != 0) {
3893 PackageParser.Package p = mAppDirs.get(fullPathStr);
3894 if (p == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08003895 p = scanPackageLI(fullPath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
3897 PackageParser.PARSE_CHATTY |
3898 PackageParser.PARSE_MUST_BE_APK,
Andrew Stadler48c02732010-01-15 00:03:41 -08003899 SCAN_MONITOR | SCAN_NO_PATHS);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003900 if (p != null) {
3901 synchronized (mPackages) {
3902 grantPermissionsLP(p, false);
3903 }
3904 addedPackage = p.applicationInfo.packageName;
3905 addedUid = p.applicationInfo.uid;
3906 }
3907 }
3908 }
3909
3910 synchronized (mPackages) {
3911 mSettings.writeLP();
3912 }
3913 }
3914
3915 if (removedPackage != null) {
3916 Bundle extras = new Bundle(1);
3917 extras.putInt(Intent.EXTRA_UID, removedUid);
3918 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
3919 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
3920 }
3921 if (addedPackage != null) {
3922 Bundle extras = new Bundle(1);
3923 extras.putInt(Intent.EXTRA_UID, addedUid);
3924 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, extras);
3925 }
3926 }
3927
3928 private final String mRootDir;
3929 private final boolean mIsRom;
3930 }
Jacek Surazski65e13172009-04-28 15:26:38 +02003931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 /* Called when a downloaded package installation has been confirmed by the user */
3933 public void installPackage(
3934 final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
Jacek Surazski65e13172009-04-28 15:26:38 +02003935 installPackage(packageURI, observer, flags, null);
3936 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003937
Jacek Surazski65e13172009-04-28 15:26:38 +02003938 /* Called when a downloaded package installation has been confirmed by the user */
3939 public void installPackage(
3940 final Uri packageURI, final IPackageInstallObserver observer, final int flags,
3941 final String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 mContext.enforceCallingOrSelfPermission(
3943 android.Manifest.permission.INSTALL_PACKAGES, null);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003944
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003945 Message msg = mHandler.obtainMessage(INIT_COPY);
3946 msg.obj = createInstallArgs(packageURI, observer, flags, installerPackageName);
3947 mHandler.sendMessage(msg);
3948 }
3949
3950 private InstallArgs createInstallArgs(Uri packageURI, IPackageInstallObserver observer,
3951 int flags, String installerPackageName) {
3952 if (installOnSd(flags)) {
3953 return new SdInstallArgs(packageURI, observer, flags,
3954 installerPackageName);
3955 } else {
3956 return new FileInstallArgs(packageURI, observer, flags,
3957 installerPackageName);
3958 }
3959 }
3960
3961 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
3962 if (installOnSd(flags)) {
3963 return new SdInstallArgs(fullCodePath, fullResourcePath);
3964 } else {
3965 return new FileInstallArgs(fullCodePath, fullResourcePath);
3966 }
3967 }
3968
3969 private void processPendingInstall(final InstallArgs args, final int currentStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003970 // Queue up an async operation since the package installation may take a little while.
3971 mHandler.post(new Runnable() {
3972 public void run() {
3973 mHandler.removeCallbacks(this);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003974 // Result object to be returned
3975 PackageInstalledInfo res = new PackageInstalledInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003976 res.returnCode = currentStatus;
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003977 res.uid = -1;
3978 res.pkg = null;
3979 res.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003980 args.doPreInstall(res.returnCode);
3981 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003982 synchronized (mInstallLock) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003983 installPackageLI(args, true, res);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07003984 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003985 args.doPostInstall(res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003986 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003987 if (args.observer != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08003989 args.observer.packageInstalled(res.name, res.returnCode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003990 } catch (RemoteException e) {
3991 Log.i(TAG, "Observer no longer exists.");
3992 }
3993 }
3994 // There appears to be a subtle deadlock condition if the sendPackageBroadcast
3995 // call appears in the synchronized block above.
3996 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
3997 res.removedInfo.sendBroadcast(false, true);
3998 Bundle extras = new Bundle(1);
3999 extras.putInt(Intent.EXTRA_UID, res.uid);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004000 final boolean update = res.removedInfo.removedPackage != null;
4001 if (update) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004002 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4003 }
4004 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
4005 res.pkg.applicationInfo.packageName,
4006 extras);
Dianne Hackbornf63220f2009-03-24 18:38:43 -07004007 if (update) {
4008 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
4009 res.pkg.applicationInfo.packageName,
4010 extras);
4011 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004012 if (res.removedInfo.args != null) {
4013 // Remove the replaced package's older resources safely now
4014 synchronized (mInstallLock) {
4015 res.removedInfo.args.cleanUpResourcesLI();
4016 }
4017 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 }
4019 Runtime.getRuntime().gc();
4020 }
4021 });
4022 }
4023
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004024 static abstract class InstallArgs {
4025 final IPackageInstallObserver observer;
4026 final int flags;
4027 final Uri packageURI;
4028 final String installerPackageName;
4029
4030 InstallArgs(Uri packageURI,
4031 IPackageInstallObserver observer, int flags,
4032 String installerPackageName) {
4033 this.packageURI = packageURI;
4034 this.flags = flags;
4035 this.observer = observer;
4036 this.installerPackageName = installerPackageName;
4037 }
4038
4039 abstract void createCopyFile();
4040 abstract int copyApk(IMediaContainerService imcs);
4041 abstract void doPreInstall(int status);
4042 abstract boolean doRename(int status, String pkgName, String oldCodePath);
4043 abstract void doPostInstall(int status);
4044 abstract String getCodePath();
4045 abstract String getResourcePath();
4046 // Need installer lock especially for dex file removal.
4047 abstract void cleanUpResourcesLI();
4048 }
4049
4050 class FileInstallArgs extends InstallArgs {
4051 File installDir;
4052 String codeFileName;
4053 String resourceFileName;
4054
4055 FileInstallArgs(Uri packageURI,
4056 IPackageInstallObserver observer, int flags,
4057 String installerPackageName) {
4058 super(packageURI, observer, flags, installerPackageName);
4059 }
4060
4061 FileInstallArgs(String fullCodePath, String fullResourcePath) {
4062 super(null, null, 0, null);
4063 File codeFile = new File(fullCodePath);
4064 installDir = codeFile.getParentFile();
4065 codeFileName = fullCodePath;
4066 resourceFileName = fullResourcePath;
4067 }
4068
4069 void createCopyFile() {
4070 boolean fwdLocked = isFwdLocked(flags);
4071 installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
4072 codeFileName = createTempPackageFile(installDir).getPath();
4073 resourceFileName = getResourcePathFromCodePath();
4074 }
4075
4076 String getCodePath() {
4077 return codeFileName;
4078 }
4079
4080 int copyApk(IMediaContainerService imcs) {
4081 // Get a ParcelFileDescriptor to write to the output file
4082 File codeFile = new File(codeFileName);
4083 ParcelFileDescriptor out = null;
4084 try {
4085 out = ParcelFileDescriptor.open(codeFile,
4086 ParcelFileDescriptor.MODE_READ_WRITE);
4087 } catch (FileNotFoundException e) {
4088 Log.e(TAG, "Failed to create file descritpor for : " + codeFileName);
4089 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4090 }
4091 // Copy the resource now
4092 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4093 try {
4094 if (imcs.copyResource(packageURI, out)) {
4095 ret = PackageManager.INSTALL_SUCCEEDED;
4096 }
4097 } catch (RemoteException e) {
4098 } finally {
4099 try { if (out != null) out.close(); } catch (IOException e) {}
4100 }
4101 return ret;
4102 }
4103
4104 void doPreInstall(int status) {
4105 if (status != PackageManager.INSTALL_SUCCEEDED) {
4106 cleanUp();
4107 }
4108 }
4109
4110 boolean doRename(int status, final String pkgName, String oldCodePath) {
4111 if (status != PackageManager.INSTALL_SUCCEEDED) {
4112 cleanUp();
4113 return false;
4114 } else {
4115 // Rename based on packageName
4116 File codeFile = new File(getCodePath());
4117 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
4118 File desFile = new File(installDir, apkName + ".apk");
4119 if (!codeFile.renameTo(desFile)) {
4120 return false;
4121 }
4122 // Reset paths since the file has been renamed.
4123 codeFileName = desFile.getPath();
4124 resourceFileName = getResourcePathFromCodePath();
4125 // Set permissions
4126 if (!setPermissions(pkgName)) {
4127 // Failed setting permissions.
4128 return false;
4129 }
4130 return true;
4131 }
4132 }
4133
4134 void doPostInstall(int status) {
4135 if (status != PackageManager.INSTALL_SUCCEEDED) {
4136 cleanUp();
4137 }
4138 }
4139
4140 String getResourcePath() {
4141 return resourceFileName;
4142 }
4143
4144 String getResourcePathFromCodePath() {
4145 String codePath = getCodePath();
4146 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
4147 String apkNameOnly = getApkName(codePath);
4148 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip";
4149 } else {
4150 return codePath;
4151 }
4152 }
4153
4154 private boolean cleanUp() {
4155 boolean ret = true;
4156 String sourceDir = getCodePath();
4157 String publicSourceDir = getResourcePath();
4158 if (sourceDir != null) {
4159 File sourceFile = new File(sourceDir);
4160 if (!sourceFile.exists()) {
4161 Log.w(TAG, "Package source " + sourceDir + " does not exist.");
4162 ret = false;
4163 }
4164 // Delete application's code and resources
4165 sourceFile.delete();
4166 }
4167 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
4168 final File publicSourceFile = new File(publicSourceDir);
4169 if (!publicSourceFile.exists()) {
4170 Log.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
4171 }
4172 if (publicSourceFile.exists()) {
4173 publicSourceFile.delete();
4174 }
4175 }
4176 return ret;
4177 }
4178
4179 void cleanUpResourcesLI() {
4180 String sourceDir = getCodePath();
4181 if (cleanUp() && mInstaller != null) {
4182 int retCode = mInstaller.rmdex(sourceDir);
4183 if (retCode < 0) {
4184 Log.w(TAG, "Couldn't remove dex file for package: "
4185 + " at location "
4186 + sourceDir + ", retcode=" + retCode);
4187 // we don't consider this to be a failure of the core package deletion
4188 }
4189 }
4190 }
4191
4192 private boolean setPermissions(String pkgName) {
4193 // TODO Do this in a more elegant way later on. for now just a hack
4194 if (!isFwdLocked(flags)) {
4195 final int filePermissions =
4196 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
4197 |FileUtils.S_IROTH;
4198 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
4199 if (retCode != 0) {
4200 Log.e(TAG, "Couldn't set new package file permissions for " +
4201 getCodePath()
4202 + ". The return code was: " + retCode);
4203 // TODO Define new internal error
4204 return false;
4205 }
4206 return true;
4207 }
4208 return true;
4209 }
4210 }
4211
4212 class SdInstallArgs extends InstallArgs {
4213 String cid;
4214 String cachePath;
4215 static final String RES_FILE_NAME = "pkg.apk";
4216
4217 SdInstallArgs(Uri packageURI,
4218 IPackageInstallObserver observer, int flags,
4219 String installerPackageName) {
4220 super(packageURI, observer, flags, installerPackageName);
4221 }
4222
4223 SdInstallArgs(String fullCodePath, String fullResourcePath) {
4224 super(null, null, 0, null);
4225 // Extract cid from fullCodePath
4226 int eidx = fullCodePath.lastIndexOf("/");
4227 String subStr1 = fullCodePath.substring(0, eidx);
4228 int sidx = subStr1.lastIndexOf("/");
4229 cid = subStr1.substring(sidx+1, eidx);
4230 cachePath = subStr1;
4231 }
4232
4233 void createCopyFile() {
4234 cid = getTempContainerId();
4235 }
4236
4237 int copyApk(IMediaContainerService imcs) {
4238 try {
4239 cachePath = imcs.copyResourceToContainer(
4240 packageURI, cid,
4241 getEncryptKey(), RES_FILE_NAME);
4242 } catch (RemoteException e) {
4243 }
4244
4245 if (cachePath != null) {
4246 // Mount container once its created with system_uid
4247 cachePath = mountSdDir(cid, Process.SYSTEM_UID);
4248 }
4249 if (cachePath == null) {
4250 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
4251 } else {
4252 return PackageManager.INSTALL_SUCCEEDED;
4253 }
4254 }
4255
4256 @Override
4257 String getCodePath() {
4258 return cachePath + "/" + RES_FILE_NAME;
4259 }
4260
4261 @Override
4262 String getResourcePath() {
4263 return cachePath + "/" + RES_FILE_NAME;
4264 }
4265
4266 void doPreInstall(int status) {
4267 if (status != PackageManager.INSTALL_SUCCEEDED) {
4268 // Destroy container
4269 destroySdDir(cid);
4270 }
4271 }
4272
4273 boolean doRename(int status, final String pkgName,
4274 String oldCodePath) {
4275 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
4276 // STOPSHIP TEMPORARY HACK FOR RENAME
4277 // Create new container at newCachePath
4278 String codePath = getCodePath();
4279 String newCachePath = null;
4280 final int CREATE_FAILED = 1;
4281 final int COPY_FAILED = 3;
4282 final int FINALIZE_FAILED = 5;
4283 final int PASS = 7;
4284 int errCode = CREATE_FAILED;
4285 if ((newCachePath = createSdDir(new File(codePath), newCacheId)) != null) {
4286 errCode = COPY_FAILED;
4287 // Copy file from codePath
4288 if (FileUtils.copyFile(new File(codePath), new File(newCachePath, RES_FILE_NAME))) {
4289 errCode = FINALIZE_FAILED;
4290 if (finalizeSdDir(newCacheId)) {
4291 errCode = PASS;
4292 }
4293 }
4294 }
4295 // Print error based on errCode
4296 String errMsg = "";
4297 switch (errCode) {
4298 case CREATE_FAILED:
4299 errMsg = "CREATE_FAILED";
4300 break;
4301 case COPY_FAILED:
4302 errMsg = "COPY_FAILED";
4303 destroySdDir(newCacheId);
4304 break;
4305 case FINALIZE_FAILED:
4306 errMsg = "FINALIZE_FAILED";
4307 destroySdDir(newCacheId);
4308 break;
4309 default:
4310 errMsg = "PASS";
4311 break;
4312 }
4313 // Destroy the temporary container
4314 destroySdDir(cid);
4315 Log.i(TAG, "Status: " + errMsg);
4316 if (errCode != PASS) {
4317 return false;
4318 }
4319 cid = newCacheId;
4320 cachePath = newCachePath;
4321
4322 return true;
4323 }
4324
4325 void doPostInstall(int status) {
4326 if (status != PackageManager.INSTALL_SUCCEEDED) {
4327 cleanUp();
4328 } else {
4329 // Unmount container
4330 // Rename and remount based on package name and new uid
4331 }
4332 }
4333
4334 private void cleanUp() {
4335 // Destroy secure container
4336 destroySdDir(cid);
4337 }
4338
4339 void cleanUpResourcesLI() {
4340 String sourceFile = getCodePath();
4341 // Remove dex file
4342 if (mInstaller != null) {
4343 int retCode = mInstaller.rmdex(sourceFile.toString());
4344 if (retCode < 0) {
4345 Log.w(TAG, "Couldn't remove dex file for package: "
4346 + " at location "
4347 + sourceFile.toString() + ", retcode=" + retCode);
4348 // we don't consider this to be a failure of the core package deletion
4349 }
4350 }
4351 cleanUp();
4352 }
4353 };
4354
4355 // Utility method used to create code paths based on package name and available index.
4356 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) {
4357 String idxStr = "";
4358 int idx = 1;
4359 if (oldCodePath != null) {
4360 int eidx = -1;
4361 if (suffix != null) {
4362 eidx = oldCodePath.indexOf(suffix);
4363 }
4364 if (eidx == -1) {
4365 eidx = oldCodePath.length();
4366 }
4367 int sidx = oldCodePath.indexOf(prefix);
4368 if (sidx == -1) {
4369 sidx = 0;
4370 }
4371 String subStr = oldCodePath.substring(sidx + prefix.length(), eidx);
4372 if (subStr != null) {
4373 if (subStr.startsWith("-")) {
4374 subStr = subStr.substring(1);
4375 }
4376 try {
4377 idx = Integer.parseInt(subStr);
4378 if (idx <= 1) {
4379 idx++;
4380 } else {
4381 idx--;
4382 }
4383 } catch(NumberFormatException e) {
4384 }
4385 }
4386 }
4387 idxStr = "-" + Integer.toString(idx);
4388 return prefix + idxStr;
4389 }
4390
4391 // Utility method that returns the relative package path with respect
4392 // to the installation directory. Like say for /data/data/com.test-1.apk
4393 // string com.test-1 is returned.
4394 static String getApkName(String codePath) {
4395 if (codePath == null) {
4396 return null;
4397 }
4398 int sidx = codePath.lastIndexOf("/");
4399 int eidx = codePath.lastIndexOf(".");
4400 if (eidx == -1) {
4401 eidx = codePath.length();
4402 } else if (eidx == 0) {
4403 Log.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
4404 return null;
4405 }
4406 return codePath.substring(sidx+1, eidx);
4407 }
4408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004409 class PackageInstalledInfo {
4410 String name;
4411 int uid;
4412 PackageParser.Package pkg;
4413 int returnCode;
4414 PackageRemovedInfo removedInfo;
4415 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 /*
4418 * Install a non-existing package.
4419 */
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004420 private void installNewPackageLI(PackageParser.Package pkg,
4421 int parseFlags,
4422 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004423 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 // Remember this for later, in case we need to rollback this install
Oscar Montemayora8529f62009-11-18 10:14:20 -08004425 boolean dataDirExists;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004426 String pkgName = pkg.packageName;
Oscar Montemayora8529f62009-11-18 10:14:20 -08004427
4428 if (useEncryptedFilesystemForPackage(pkg)) {
4429 dataDirExists = (new File(mSecureAppDataDir, pkgName)).exists();
4430 } else {
4431 dataDirExists = (new File(mAppDataDir, pkgName)).exists();
4432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004433 res.name = pkgName;
4434 synchronized(mPackages) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004435 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 // Don't allow installation over an existing package with the same name.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004437 Log.w(TAG, "Attempt to re-install " + pkgName
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 + " without first uninstalling.");
4439 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
4440 return;
4441 }
4442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004444 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004445 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004446 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4448 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4449 }
4450 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004451 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004452 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 res);
4454 // delete the partially installed application. the data directory will have to be
4455 // restored if it was already existing
4456 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4457 // remove package from internal structures. Note that we want deletePackageX to
4458 // delete the package data and cache directories that it created in
4459 // scanPackageLocked, unless those directories existed before we even tried to
4460 // install.
4461 deletePackageLI(
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004462 pkgName, false,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0,
4464 res.removedInfo);
4465 }
4466 }
4467 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004468
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004469 private void replacePackageLI(PackageParser.Package pkg,
4470 int parseFlags,
4471 int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004472 String installerPackageName, PackageInstalledInfo res) {
4473
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004474 PackageParser.Package oldPackage;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004475 String pkgName = pkg.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 // First find the old package info and check signatures
4477 synchronized(mPackages) {
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004478 oldPackage = mPackages.get(pkgName);
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07004479 if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
4480 != PackageManager.SIGNATURE_MATCH) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004481 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
4482 return;
4483 }
4484 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07004485 boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 if(sysPkg) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004487 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004488 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004489 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004490 }
4491 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004493 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004494 PackageParser.Package pkg,
4495 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004496 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 PackageParser.Package newPackage = null;
4498 String pkgName = deletedPackage.packageName;
4499 boolean deletedPkg = true;
4500 boolean updatedSettings = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004501
Jacek Surazski65e13172009-04-28 15:26:38 +02004502 String oldInstallerPackageName = null;
4503 synchronized (mPackages) {
4504 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
4505 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004506
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004507 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 // First delete the existing package while retaining the data directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004509 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004510 res.removedInfo)) {
4511 // If the existing package was'nt successfully deleted
4512 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4513 deletedPkg = false;
4514 } else {
4515 // Successfully deleted the old package. Now proceed with re-installation
4516 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004517 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004519 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004520 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4521 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
Suchi Amalapurapu110fea72010-01-14 17:50:23 -08004522 }
4523 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004524 updateSettingsLI(newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004525 installerPackageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 res);
4527 updatedSettings = true;
4528 }
4529 }
4530
4531 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4532 // If we deleted an exisiting package, the old source and resource files that we
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004533 // were keeping around in case we needed them (see below) can now be deleted.
4534 // This info will be set on the res.removedInfo to clean up later on as post
4535 // install action.
4536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 //update signature on the new package setting
4538 //this should always succeed, since we checked the
4539 //signature earlier.
4540 synchronized(mPackages) {
4541 verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
4542 parseFlags, true);
4543 }
4544 } else {
4545 // remove package from internal structures. Note that we want deletePackageX to
4546 // delete the package data and cache directories that it created in
4547 // scanPackageLocked, unless those directories existed before we even tried to
4548 // install.
4549 if(updatedSettings) {
4550 deletePackageLI(
4551 pkgName, true,
4552 PackageManager.DONT_DELETE_DATA,
4553 res.removedInfo);
4554 }
4555 // Since we failed to install the new package we need to restore the old
4556 // package that we deleted.
4557 if(deletedPkg) {
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004558 File restoreFile = new File(deletedPackage.mPath);
4559 if (restoreFile == null) {
4560 Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
4561 return;
4562 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004563 PackageInstalledInfo restoreRes = new PackageInstalledInfo();
4564 restoreRes.removedInfo = new PackageRemovedInfo();
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004565 // Parse old package
4566 parseFlags |= ~PackageManager.INSTALL_REPLACE_EXISTING;
4567 scanPackageLI(restoreFile, parseFlags, scanMode);
4568 synchronized (mPackages) {
4569 grantPermissionsLP(deletedPackage, false);
4570 mSettings.writeLP();
4571 }
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004572 if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4573 Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
4574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 }
4576 }
4577 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004580 PackageParser.Package pkg,
4581 int parseFlags, int scanMode,
Jacek Surazski65e13172009-04-28 15:26:38 +02004582 String installerPackageName, PackageInstalledInfo res) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004583 PackageParser.Package newPackage = null;
4584 boolean updatedSettings = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004585 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 PackageParser.PARSE_IS_SYSTEM;
4587 String packageName = deletedPackage.packageName;
4588 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
4589 if (packageName == null) {
4590 Log.w(TAG, "Attempt to delete null packageName.");
4591 return;
4592 }
4593 PackageParser.Package oldPkg;
4594 PackageSetting oldPkgSetting;
4595 synchronized (mPackages) {
4596 oldPkg = mPackages.get(packageName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004597 oldPkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004598 if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
4599 (oldPkgSetting == null)) {
4600 Log.w(TAG, "Could'nt find package:"+packageName+" information");
4601 return;
4602 }
4603 }
4604 res.removedInfo.uid = oldPkg.applicationInfo.uid;
4605 res.removedInfo.removedPackage = packageName;
4606 // Remove existing system package
4607 removePackageLI(oldPkg, true);
4608 synchronized (mPackages) {
4609 res.removedInfo.removedUid = mSettings.disableSystemPackageLP(packageName);
4610 }
4611
4612 // Successfully disabled the old package. Now proceed with re-installation
4613 mLastScanError = PackageManager.INSTALL_SUCCEEDED;
4614 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004615 newPackage = scanPackageLI(pkg, parseFlags, scanMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 if (newPackage == null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004617 Log.w(TAG, "Package couldn't be installed in " + pkg.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004618 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
4619 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK;
4620 }
4621 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004622 updateSettingsLI(newPackage, installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 updatedSettings = true;
4624 }
4625
4626 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
4627 //update signature on the new package setting
4628 //this should always succeed, since we checked the
4629 //signature earlier.
4630 synchronized(mPackages) {
4631 verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
4632 parseFlags, true);
4633 }
4634 } else {
4635 // Re installation failed. Restore old information
4636 // Remove new pkg information
Dianne Hackborn62da8462009-05-13 15:06:13 -07004637 if (newPackage != null) {
4638 removePackageLI(newPackage, true);
4639 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 // Add back the old system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004641 scanPackageLI(oldPkg, parseFlags,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 SCAN_MONITOR
The Android Open Source Project10592532009-03-18 17:39:46 -07004643 | SCAN_UPDATE_SIGNATURE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 // Restore the old system information in Settings
4645 synchronized(mPackages) {
4646 if(updatedSettings) {
4647 mSettings.enableSystemPackageLP(packageName);
Jacek Surazski65e13172009-04-28 15:26:38 +02004648 mSettings.setInstallerPackageName(packageName,
4649 oldPkgSetting.installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004650 }
4651 mSettings.writeLP();
4652 }
4653 }
4654 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004655
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004656 private void updateSettingsLI(PackageParser.Package newPackage,
Jacek Surazski65e13172009-04-28 15:26:38 +02004657 String installerPackageName, PackageInstalledInfo res) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004658 String pkgName = newPackage.packageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 synchronized (mPackages) {
4660 //write settings. the installStatus will be incomplete at this stage.
4661 //note that the new package setting would have already been
4662 //added to mPackages. It hasn't been persisted yet.
4663 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE);
4664 mSettings.writeLP();
4665 }
4666
4667 int retCode = 0;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004668 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
4669 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004671 Log.e(TAG, "Couldn't rename dex file: " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4673 return;
4674 }
4675 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004676 res.returnCode = setPermissionsLI(newPackage);
4677 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4678 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004680 Log.d(TAG, "New package installed in " + newPackage.mPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 }
4682 if(res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
4683 if (mInstaller != null) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004684 mInstaller.rmdex(newPackage.mScanPath);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004685 }
4686 }
4687
4688 synchronized (mPackages) {
4689 grantPermissionsLP(newPackage, true);
4690 res.name = pkgName;
4691 res.uid = newPackage.applicationInfo.uid;
4692 res.pkg = newPackage;
4693 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE);
Jacek Surazski65e13172009-04-28 15:26:38 +02004694 mSettings.setInstallerPackageName(pkgName, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4696 //to update install status
4697 mSettings.writeLP();
4698 }
4699 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004700
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004701 private void installPackageLI(InstallArgs args,
4702 boolean newInstall, PackageInstalledInfo res) {
4703 int pFlags = args.flags;
4704 String installerPackageName = args.installerPackageName;
4705 File tmpPackageFile = new File(args.getCodePath());
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004706 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
4707 boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004708 boolean replacingExistingPackage = false;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004709 int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
4710 | (newInstall ? SCAN_NEW_INSTALL : 0);
Suchi Amalapurapuee5ece42009-09-15 13:41:47 -07004711 // Result object to be returned
4712 res.returnCode = PackageManager.INSTALL_SUCCEEDED;
4713
4714 main_flow: try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004715 // Retrieve PackageSettings and parse package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004716 int parseFlags = PackageParser.PARSE_CHATTY |
4717 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
4718 (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004719 parseFlags |= mDefParseFlags;
4720 PackageParser pp = new PackageParser(tmpPackageFile.getPath());
4721 pp.setSeparateProcesses(mSeparateProcesses);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004722 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004723 null, mMetrics, parseFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004724 if (pkg == null) {
4725 res.returnCode = pp.getParseError();
4726 break main_flow;
4727 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004728 String pkgName = res.name = pkg.packageName;
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004729 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
4730 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
4731 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
4732 break main_flow;
4733 }
4734 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004735 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
4736 res.returnCode = pp.getParseError();
4737 break main_flow;
4738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004739
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004740 // Get rid of all references to package scan path via parser.
4741 pp = null;
4742 String oldCodePath = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004743 synchronized (mPackages) {
4744 //check if installing already existing package
Dianne Hackbornade3eca2009-05-11 18:54:45 -07004745 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004746 && mPackages.containsKey(pkgName)) {
4747 replacingExistingPackage = true;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004748 oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 }
4750 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004751
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004752 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
4753 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4754 break main_flow;
4755 }
4756 // TODO rename pkg.mScanPath In scanPackageLI let it just set values based on mScanPath
4757 pkg.applicationInfo.sourceDir = pkg.mScanPath= pkg.mPath = args.getCodePath();
4758 pkg.applicationInfo.publicSourceDir = args.getResourcePath();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004759 if(replacingExistingPackage) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004760 replacePackageLI(pkg, parseFlags, scanMode,
4761 installerPackageName, res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004762 } else {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004763 installNewPackageLI(pkg, parseFlags, scanMode,
4764 installerPackageName,res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004765 }
4766 } finally {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004767 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004768 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004769 }
4770 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004771
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004772 private int setPermissionsLI(PackageParser.Package newPackage) {
4773 String pkgName = newPackage.packageName;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004774 int retCode = 0;
4775 // TODO Gross hack but fix later. Ideally move this to be a post installation
4776 // check after alloting uid.
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004777 if ((newPackage.applicationInfo.flags
4778 & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
4779 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 try {
4781 extractPublicFiles(newPackage, destResourceFile);
4782 } catch (IOException e) {
4783 Log.e(TAG, "Couldn't create a new zip file for the public parts of a" +
4784 " forward-locked app.");
4785 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
4786 } finally {
4787 //TODO clean up the extracted public files
4788 }
4789 if (mInstaller != null) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004790 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 newPackage.applicationInfo.uid);
4792 } else {
4793 final int filePermissions =
4794 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004795 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 newPackage.applicationInfo.uid);
4797 }
4798 } else {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004799 // The permissions on the resource file was set when it was copied for
4800 // non forward locked apps and apps on sdcard
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004803 if (retCode != 0) {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004804 Log.e(TAG, "Couldn't set new package file permissions for " +
4805 newPackage.mPath
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 + ". The return code was: " + retCode);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004807 // TODO Define new internal error
4808 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004809 }
4810 return PackageManager.INSTALL_SUCCEEDED;
4811 }
4812
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08004813 private boolean isForwardLocked(PackageParser.Package pkg) {
4814 return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815 }
4816
4817 private void extractPublicFiles(PackageParser.Package newPackage,
4818 File publicZipFile) throws IOException {
4819 final ZipOutputStream publicZipOutStream =
4820 new ZipOutputStream(new FileOutputStream(publicZipFile));
4821 final ZipFile privateZip = new ZipFile(newPackage.mPath);
4822
4823 // Copy manifest, resources.arsc and res directory to public zip
4824
4825 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries();
4826 while (privateZipEntries.hasMoreElements()) {
4827 final ZipEntry zipEntry = privateZipEntries.nextElement();
4828 final String zipEntryName = zipEntry.getName();
4829 if ("AndroidManifest.xml".equals(zipEntryName)
4830 || "resources.arsc".equals(zipEntryName)
4831 || zipEntryName.startsWith("res/")) {
4832 try {
4833 copyZipEntry(zipEntry, privateZip, publicZipOutStream);
4834 } catch (IOException e) {
4835 try {
4836 publicZipOutStream.close();
4837 throw e;
4838 } finally {
4839 publicZipFile.delete();
4840 }
4841 }
4842 }
4843 }
4844
4845 publicZipOutStream.close();
4846 FileUtils.setPermissions(
4847 publicZipFile.getAbsolutePath(),
4848 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH,
4849 -1, -1);
4850 }
4851
4852 private static void copyZipEntry(ZipEntry zipEntry,
4853 ZipFile inZipFile,
4854 ZipOutputStream outZipStream) throws IOException {
4855 byte[] buffer = new byte[4096];
4856 int num;
4857
4858 ZipEntry newEntry;
4859 if (zipEntry.getMethod() == ZipEntry.STORED) {
4860 // Preserve the STORED method of the input entry.
4861 newEntry = new ZipEntry(zipEntry);
4862 } else {
4863 // Create a new entry so that the compressed len is recomputed.
4864 newEntry = new ZipEntry(zipEntry.getName());
4865 }
4866 outZipStream.putNextEntry(newEntry);
4867
4868 InputStream data = inZipFile.getInputStream(zipEntry);
4869 while ((num = data.read(buffer)) > 0) {
4870 outZipStream.write(buffer, 0, num);
4871 }
4872 outZipStream.flush();
4873 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004875 private void deleteTempPackageFiles() {
4876 FilenameFilter filter = new FilenameFilter() {
4877 public boolean accept(File dir, String name) {
4878 return name.startsWith("vmdl") && name.endsWith(".tmp");
4879 }
4880 };
4881 String tmpFilesList[] = mAppInstallDir.list(filter);
4882 if(tmpFilesList == null) {
4883 return;
4884 }
4885 for(int i = 0; i < tmpFilesList.length; i++) {
4886 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]);
4887 tmpFile.delete();
4888 }
4889 }
4890
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004891 private File createTempPackageFile(File installDir) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 File tmpPackageFile;
4893 try {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004894 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 } catch (IOException e) {
4896 Log.e(TAG, "Couldn't create temp file for downloaded package file.");
4897 return null;
4898 }
4899 try {
4900 FileUtils.setPermissions(
4901 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
4902 -1, -1);
4903 } catch (IOException e) {
4904 Log.e(TAG, "Trouble getting the canoncical path for a temp file.");
4905 return null;
4906 }
4907 return tmpPackageFile;
4908 }
4909
4910 public void deletePackage(final String packageName,
4911 final IPackageDeleteObserver observer,
4912 final int flags) {
4913 mContext.enforceCallingOrSelfPermission(
4914 android.Manifest.permission.DELETE_PACKAGES, null);
4915 // Queue up an async operation since the package deletion may take a little while.
4916 mHandler.post(new Runnable() {
4917 public void run() {
4918 mHandler.removeCallbacks(this);
4919 final boolean succeded = deletePackageX(packageName, true, true, flags);
4920 if (observer != null) {
4921 try {
4922 observer.packageDeleted(succeded);
4923 } catch (RemoteException e) {
4924 Log.i(TAG, "Observer no longer exists.");
4925 } //end catch
4926 } //end if
4927 } //end run
4928 });
4929 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004931 /**
4932 * This method is an internal method that could be get invoked either
4933 * to delete an installed package or to clean up a failed installation.
4934 * After deleting an installed package, a broadcast is sent to notify any
4935 * listeners that the package has been installed. For cleaning up a failed
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004936 * installation, the broadcast is not necessary since the package's
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004937 * installation wouldn't have sent the initial broadcast either
4938 * The key steps in deleting a package are
4939 * deleting the package information in internal structures like mPackages,
4940 * deleting the packages base directories through installd
4941 * updating mSettings to reflect current status
4942 * persisting settings for later use
4943 * sending a broadcast if necessary
4944 */
4945
4946 private boolean deletePackageX(String packageName, boolean sendBroadCast,
4947 boolean deleteCodeAndResources, int flags) {
4948 PackageRemovedInfo info = new PackageRemovedInfo();
Romain Guy96f43572009-03-24 20:27:49 -07004949 boolean res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004950
4951 synchronized (mInstallLock) {
4952 res = deletePackageLI(packageName, deleteCodeAndResources, flags, info);
4953 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004955 if(res && sendBroadCast) {
Romain Guy96f43572009-03-24 20:27:49 -07004956 boolean systemUpdate = info.isRemovedPackageSystemUpdate;
4957 info.sendBroadcast(deleteCodeAndResources, systemUpdate);
4958
4959 // If the removed package was a system update, the old system packaged
4960 // was re-enabled; we need to broadcast this information
4961 if (systemUpdate) {
4962 Bundle extras = new Bundle(1);
4963 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid);
4964 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4965
4966 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras);
4967 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras);
4968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004969 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004970 // Delete the resources here after sending the broadcast to let
4971 // other processes clean up before deleting resources.
4972 synchronized (mInstallLock) {
4973 if (info.args != null) {
4974 info.args.cleanUpResourcesLI();
4975 }
4976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004977 return res;
4978 }
4979
4980 static class PackageRemovedInfo {
4981 String removedPackage;
4982 int uid = -1;
4983 int removedUid = -1;
Romain Guy96f43572009-03-24 20:27:49 -07004984 boolean isRemovedPackageSystemUpdate = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08004985 // Clean up resources deleted packages.
4986 InstallArgs args = null;
Romain Guy96f43572009-03-24 20:27:49 -07004987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 void sendBroadcast(boolean fullRemove, boolean replacing) {
4989 Bundle extras = new Bundle(1);
4990 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid);
4991 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove);
4992 if (replacing) {
4993 extras.putBoolean(Intent.EXTRA_REPLACING, true);
4994 }
4995 if (removedPackage != null) {
4996 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras);
4997 }
4998 if (removedUid >= 0) {
4999 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras);
5000 }
5001 }
5002 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 /*
5005 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA
5006 * flag is not set, the data directory is removed as well.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005007 * 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 -08005008 * delete a partially installed application.
5009 */
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005010 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 int flags) {
5012 String packageName = p.packageName;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005013 if (outInfo != null) {
5014 outInfo.removedPackage = packageName;
5015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 removePackageLI(p, true);
5017 // Retrieve object to delete permissions for shared user later on
5018 PackageSetting deletedPs;
5019 synchronized (mPackages) {
5020 deletedPs = mSettings.mPackages.get(packageName);
5021 }
5022 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005023 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005024 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005025 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 if (retCode < 0) {
5027 Log.w(TAG, "Couldn't remove app data or cache directory for package: "
5028 + packageName + ", retcode=" + retCode);
5029 // we don't consider this to be a failure of the core package deletion
5030 }
5031 } else {
5032 //for emulator
5033 PackageParser.Package pkg = mPackages.get(packageName);
5034 File dataDir = new File(pkg.applicationInfo.dataDir);
5035 dataDir.delete();
5036 }
5037 synchronized (mPackages) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005038 if (outInfo != null) {
5039 outInfo.removedUid = mSettings.removePackageLP(packageName);
5040 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 }
5042 }
5043 synchronized (mPackages) {
5044 if ( (deletedPs != null) && (deletedPs.sharedUser != null)) {
5045 // remove permissions associated with package
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07005046 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005047 }
5048 // Save settings now
5049 mSettings.writeLP ();
5050 }
5051 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005053 /*
5054 * Tries to delete system package.
5055 */
5056 private boolean deleteSystemPackageLI(PackageParser.Package p,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005057 int flags, PackageRemovedInfo outInfo) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 ApplicationInfo applicationInfo = p.applicationInfo;
5059 //applicable for non-partially installed applications only
5060 if (applicationInfo == null) {
5061 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5062 return false;
5063 }
5064 PackageSetting ps = null;
5065 // Confirm if the system package has been updated
5066 // An updated system app can be deleted. This will also have to restore
5067 // the system pkg from system partition
5068 synchronized (mPackages) {
5069 ps = mSettings.getDisabledSystemPkg(p.packageName);
5070 }
5071 if (ps == null) {
5072 Log.w(TAG, "Attempt to delete system package "+ p.packageName);
5073 return false;
5074 } else {
5075 Log.i(TAG, "Deleting system pkg from data partition");
5076 }
5077 // Delete the updated package
Romain Guy96f43572009-03-24 20:27:49 -07005078 outInfo.isRemovedPackageSystemUpdate = true;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005079 boolean deleteCodeAndResources = false;
5080 if (ps.versionCode < p.mVersionCode) {
5081 // Delete code and resources for downgrades
5082 deleteCodeAndResources = true;
5083 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5084 flags &= ~PackageManager.DONT_DELETE_DATA;
5085 }
5086 } else {
5087 // Preserve data by setting flag
5088 if ((flags & PackageManager.DONT_DELETE_DATA) == 0) {
5089 flags |= PackageManager.DONT_DELETE_DATA;
5090 }
5091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo);
5093 if (!ret) {
5094 return false;
5095 }
5096 synchronized (mPackages) {
5097 // Reinstate the old system package
5098 mSettings.enableSystemPackageLP(p.packageName);
5099 }
5100 // Install the system package
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005101 PackageParser.Package newPkg = scanPackageLI(ps.codePath,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM,
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005103 SCAN_MONITOR | SCAN_NO_PATHS);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 if (newPkg == null) {
5106 Log.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError);
5107 return false;
5108 }
5109 synchronized (mPackages) {
Suchi Amalapurapu701f5162009-06-03 15:47:55 -07005110 grantPermissionsLP(newPkg, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005111 mSettings.writeLP();
5112 }
5113 return true;
5114 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 private boolean deleteInstalledPackageLI(PackageParser.Package p,
5117 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5118 ApplicationInfo applicationInfo = p.applicationInfo;
5119 if (applicationInfo == null) {
5120 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5121 return false;
5122 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07005123 if (outInfo != null) {
5124 outInfo.uid = applicationInfo.uid;
5125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005126
5127 // Delete package data from internal structures and also remove data if flag is set
5128 removePackageDataLI(p, outInfo, flags);
5129
5130 // Delete application code and resources
5131 if (deleteCodeAndResources) {
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005132 // TODO can pick up from PackageSettings as well
5133 int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
5134 PackageManager.INSTALL_ON_SDCARD : 0;
5135 installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
5136 PackageManager.INSTALL_FORWARD_LOCK : 0;
5137 outInfo.args = createInstallArgs(installFlags,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07005138 applicationInfo.sourceDir, applicationInfo.publicSourceDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139 }
5140 return true;
5141 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 /*
5144 * This method handles package deletion in general
5145 */
5146 private boolean deletePackageLI(String packageName,
5147 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo) {
5148 if (packageName == null) {
5149 Log.w(TAG, "Attempt to delete null packageName.");
5150 return false;
5151 }
5152 PackageParser.Package p;
5153 boolean dataOnly = false;
5154 synchronized (mPackages) {
5155 p = mPackages.get(packageName);
5156 if (p == null) {
5157 //this retrieves partially installed apps
5158 dataOnly = true;
5159 PackageSetting ps = mSettings.mPackages.get(packageName);
5160 if (ps == null) {
5161 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5162 return false;
5163 }
5164 p = ps.pkg;
5165 }
5166 }
5167 if (p == null) {
5168 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5169 return false;
5170 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 if (dataOnly) {
5173 // Delete application data first
5174 removePackageDataLI(p, outInfo, flags);
5175 return true;
5176 }
5177 // At this point the package should have ApplicationInfo associated with it
5178 if (p.applicationInfo == null) {
5179 Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
5180 return false;
5181 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005182 boolean ret = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005183 if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
5184 Log.i(TAG, "Removing system package:"+p.packageName);
5185 // When an updated system application is deleted we delete the existing resources as well and
5186 // fall back to existing code in system partition
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005187 ret = deleteSystemPackageLI(p, flags, outInfo);
5188 } else {
5189 Log.i(TAG, "Removing non-system package:"+p.packageName);
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08005190 // Kill application pre-emptively especially for apps on sd.
5191 killApplication(packageName, p.applicationInfo.uid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005192 ret = deleteInstalledPackageLI (p, deleteCodeAndResources, flags, outInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005193 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08005194 return ret;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 public void clearApplicationUserData(final String packageName,
5198 final IPackageDataObserver observer) {
5199 mContext.enforceCallingOrSelfPermission(
5200 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
5201 // Queue up an async operation since the package deletion may take a little while.
5202 mHandler.post(new Runnable() {
5203 public void run() {
5204 mHandler.removeCallbacks(this);
5205 final boolean succeeded;
5206 synchronized (mInstallLock) {
5207 succeeded = clearApplicationUserDataLI(packageName);
5208 }
5209 if (succeeded) {
5210 // invoke DeviceStorageMonitor's update method to clear any notifications
5211 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService)
5212 ServiceManager.getService(DeviceStorageMonitorService.SERVICE);
5213 if (dsm != null) {
5214 dsm.updateMemory();
5215 }
5216 }
5217 if(observer != null) {
5218 try {
5219 observer.onRemoveCompleted(packageName, succeeded);
5220 } catch (RemoteException e) {
5221 Log.i(TAG, "Observer no longer exists.");
5222 }
5223 } //end if observer
5224 } //end run
5225 });
5226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 private boolean clearApplicationUserDataLI(String packageName) {
5229 if (packageName == null) {
5230 Log.w(TAG, "Attempt to delete null packageName.");
5231 return false;
5232 }
5233 PackageParser.Package p;
5234 boolean dataOnly = false;
5235 synchronized (mPackages) {
5236 p = mPackages.get(packageName);
5237 if(p == null) {
5238 dataOnly = true;
5239 PackageSetting ps = mSettings.mPackages.get(packageName);
5240 if((ps == null) || (ps.pkg == null)) {
5241 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5242 return false;
5243 }
5244 p = ps.pkg;
5245 }
5246 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005247 boolean useEncryptedFSDir = false;
5248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 if(!dataOnly) {
5250 //need to check this only for fully installed applications
5251 if (p == null) {
5252 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5253 return false;
5254 }
5255 final ApplicationInfo applicationInfo = p.applicationInfo;
5256 if (applicationInfo == null) {
5257 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5258 return false;
5259 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005260 useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 }
5262 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005263 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 if (retCode < 0) {
5265 Log.w(TAG, "Couldn't remove cache files for package: "
5266 + packageName);
5267 return false;
5268 }
5269 }
5270 return true;
5271 }
5272
5273 public void deleteApplicationCacheFiles(final String packageName,
5274 final IPackageDataObserver observer) {
5275 mContext.enforceCallingOrSelfPermission(
5276 android.Manifest.permission.DELETE_CACHE_FILES, null);
5277 // Queue up an async operation since the package deletion may take a little while.
5278 mHandler.post(new Runnable() {
5279 public void run() {
5280 mHandler.removeCallbacks(this);
5281 final boolean succeded;
5282 synchronized (mInstallLock) {
5283 succeded = deleteApplicationCacheFilesLI(packageName);
5284 }
5285 if(observer != null) {
5286 try {
5287 observer.onRemoveCompleted(packageName, succeded);
5288 } catch (RemoteException e) {
5289 Log.i(TAG, "Observer no longer exists.");
5290 }
5291 } //end if observer
5292 } //end run
5293 });
5294 }
5295
5296 private boolean deleteApplicationCacheFilesLI(String packageName) {
5297 if (packageName == null) {
5298 Log.w(TAG, "Attempt to delete null packageName.");
5299 return false;
5300 }
5301 PackageParser.Package p;
5302 synchronized (mPackages) {
5303 p = mPackages.get(packageName);
5304 }
5305 if (p == null) {
5306 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5307 return false;
5308 }
5309 final ApplicationInfo applicationInfo = p.applicationInfo;
5310 if (applicationInfo == null) {
5311 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5312 return false;
5313 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005314 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005315 if (mInstaller != null) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08005316 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 if (retCode < 0) {
5318 Log.w(TAG, "Couldn't remove cache files for package: "
5319 + packageName);
5320 return false;
5321 }
5322 }
5323 return true;
5324 }
5325
5326 public void getPackageSizeInfo(final String packageName,
5327 final IPackageStatsObserver observer) {
5328 mContext.enforceCallingOrSelfPermission(
5329 android.Manifest.permission.GET_PACKAGE_SIZE, null);
5330 // Queue up an async operation since the package deletion may take a little while.
5331 mHandler.post(new Runnable() {
5332 public void run() {
5333 mHandler.removeCallbacks(this);
5334 PackageStats lStats = new PackageStats(packageName);
5335 final boolean succeded;
5336 synchronized (mInstallLock) {
5337 succeded = getPackageSizeInfoLI(packageName, lStats);
5338 }
5339 if(observer != null) {
5340 try {
5341 observer.onGetStatsCompleted(lStats, succeded);
5342 } catch (RemoteException e) {
5343 Log.i(TAG, "Observer no longer exists.");
5344 }
5345 } //end if observer
5346 } //end run
5347 });
5348 }
5349
5350 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) {
5351 if (packageName == null) {
5352 Log.w(TAG, "Attempt to get size of null packageName.");
5353 return false;
5354 }
5355 PackageParser.Package p;
5356 boolean dataOnly = false;
5357 synchronized (mPackages) {
5358 p = mPackages.get(packageName);
5359 if(p == null) {
5360 dataOnly = true;
5361 PackageSetting ps = mSettings.mPackages.get(packageName);
5362 if((ps == null) || (ps.pkg == null)) {
5363 Log.w(TAG, "Package named '" + packageName +"' doesn't exist.");
5364 return false;
5365 }
5366 p = ps.pkg;
5367 }
5368 }
5369 String publicSrcDir = null;
5370 if(!dataOnly) {
5371 final ApplicationInfo applicationInfo = p.applicationInfo;
5372 if (applicationInfo == null) {
5373 Log.w(TAG, "Package " + packageName + " has no applicationInfo.");
5374 return false;
5375 }
5376 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
5377 }
Oscar Montemayora8529f62009-11-18 10:14:20 -08005378 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 if (mInstaller != null) {
5380 int res = mInstaller.getSizeInfo(packageName, p.mPath,
Oscar Montemayora8529f62009-11-18 10:14:20 -08005381 publicSrcDir, pStats, useEncryptedFSDir);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 if (res < 0) {
5383 return false;
5384 } else {
5385 return true;
5386 }
5387 }
5388 return true;
5389 }
5390
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005392 public void addPackageToPreferred(String packageName) {
5393 mContext.enforceCallingOrSelfPermission(
5394 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005395 Log.w(TAG, "addPackageToPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 }
5397
5398 public void removePackageFromPreferred(String packageName) {
5399 mContext.enforceCallingOrSelfPermission(
5400 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005401 Log.w(TAG, "removePackageFromPreferred: no longer implemented");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005402 }
5403
5404 public List<PackageInfo> getPreferredPackages(int flags) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08005405 return new ArrayList<PackageInfo>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005406 }
5407
5408 public void addPreferredActivity(IntentFilter filter, int match,
5409 ComponentName[] set, ComponentName activity) {
5410 mContext.enforceCallingOrSelfPermission(
5411 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5412
5413 synchronized (mPackages) {
5414 Log.i(TAG, "Adding preferred activity " + activity + ":");
5415 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5416 mSettings.mPreferredActivities.addFilter(
5417 new PreferredActivity(filter, match, set, activity));
5418 mSettings.writeLP();
5419 }
5420 }
5421
Satish Sampath8dbe6122009-06-02 23:35:54 +01005422 public void replacePreferredActivity(IntentFilter filter, int match,
5423 ComponentName[] set, ComponentName activity) {
5424 mContext.enforceCallingOrSelfPermission(
5425 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5426 if (filter.countActions() != 1) {
5427 throw new IllegalArgumentException(
5428 "replacePreferredActivity expects filter to have only 1 action.");
5429 }
5430 if (filter.countCategories() != 1) {
5431 throw new IllegalArgumentException(
5432 "replacePreferredActivity expects filter to have only 1 category.");
5433 }
5434 if (filter.countDataAuthorities() != 0
5435 || filter.countDataPaths() != 0
5436 || filter.countDataSchemes() != 0
5437 || filter.countDataTypes() != 0) {
5438 throw new IllegalArgumentException(
5439 "replacePreferredActivity expects filter to have no data authorities, " +
5440 "paths, schemes or types.");
5441 }
5442 synchronized (mPackages) {
5443 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5444 String action = filter.getAction(0);
5445 String category = filter.getCategory(0);
5446 while (it.hasNext()) {
5447 PreferredActivity pa = it.next();
5448 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
5449 it.remove();
5450 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":");
5451 filter.dump(new LogPrinter(Log.INFO, TAG), " ");
5452 }
5453 }
5454 addPreferredActivity(filter, match, set, activity);
5455 }
5456 }
5457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 public void clearPackagePreferredActivities(String packageName) {
5459 mContext.enforceCallingOrSelfPermission(
5460 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
5461
5462 synchronized (mPackages) {
5463 if (clearPackagePreferredActivitiesLP(packageName)) {
5464 mSettings.writeLP();
5465 }
5466 }
5467 }
5468
5469 boolean clearPackagePreferredActivitiesLP(String packageName) {
5470 boolean changed = false;
5471 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5472 while (it.hasNext()) {
5473 PreferredActivity pa = it.next();
5474 if (pa.mActivity.getPackageName().equals(packageName)) {
5475 it.remove();
5476 changed = true;
5477 }
5478 }
5479 return changed;
5480 }
5481
5482 public int getPreferredActivities(List<IntentFilter> outFilters,
5483 List<ComponentName> outActivities, String packageName) {
5484
5485 int num = 0;
5486 synchronized (mPackages) {
5487 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
5488 while (it.hasNext()) {
5489 PreferredActivity pa = it.next();
5490 if (packageName == null
5491 || pa.mActivity.getPackageName().equals(packageName)) {
5492 if (outFilters != null) {
5493 outFilters.add(new IntentFilter(pa));
5494 }
5495 if (outActivities != null) {
5496 outActivities.add(pa.mActivity);
5497 }
5498 }
5499 }
5500 }
5501
5502 return num;
5503 }
5504
5505 public void setApplicationEnabledSetting(String appPackageName,
5506 int newState, int flags) {
5507 setEnabledSetting(appPackageName, null, newState, flags);
5508 }
5509
5510 public void setComponentEnabledSetting(ComponentName componentName,
5511 int newState, int flags) {
5512 setEnabledSetting(componentName.getPackageName(),
5513 componentName.getClassName(), newState, flags);
5514 }
5515
5516 private void setEnabledSetting(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005517 final String packageName, String className, int newState, final int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
5519 || newState == COMPONENT_ENABLED_STATE_ENABLED
5520 || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
5521 throw new IllegalArgumentException("Invalid new component state: "
5522 + newState);
5523 }
5524 PackageSetting pkgSetting;
5525 final int uid = Binder.getCallingUid();
5526 final int permission = mContext.checkCallingPermission(
5527 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
5528 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005529 boolean sendNow = false;
5530 boolean isApp = (className == null);
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005531 String componentName = isApp ? packageName : className;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005532 int packageUid = -1;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005533 ArrayList<String> components;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 synchronized (mPackages) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005535 pkgSetting = mSettings.mPackages.get(packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 if (pkgSetting == null) {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005537 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005538 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005539 "Unknown package: " + packageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005540 }
5541 throw new IllegalArgumentException(
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005542 "Unknown component: " + packageName
5543 + "/" + className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005544 }
5545 if (!allowedByPermission && (uid != pkgSetting.userId)) {
5546 throw new SecurityException(
5547 "Permission Denial: attempt to change component state from pid="
5548 + Binder.getCallingPid()
5549 + ", uid=" + uid + ", package uid=" + pkgSetting.userId);
5550 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005551 if (className == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005552 // We're dealing with an application/package level state change
5553 pkgSetting.enabled = newState;
5554 } else {
5555 // We're dealing with a component level state change
5556 switch (newState) {
5557 case COMPONENT_ENABLED_STATE_ENABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005558 pkgSetting.enableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005559 break;
5560 case COMPONENT_ENABLED_STATE_DISABLED:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005561 pkgSetting.disableComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 break;
5563 case COMPONENT_ENABLED_STATE_DEFAULT:
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005564 pkgSetting.restoreComponentLP(className);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005565 break;
5566 default:
5567 Log.e(TAG, "Invalid new component state: " + newState);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005568 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 }
5570 }
5571 mSettings.writeLP();
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005572 packageUid = pkgSetting.userId;
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005573 components = mPendingBroadcasts.get(packageName);
5574 boolean newPackage = components == null;
5575 if (newPackage) {
5576 components = new ArrayList<String>();
5577 }
5578 if (!components.contains(componentName)) {
5579 components.add(componentName);
5580 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005581 if ((flags&PackageManager.DONT_KILL_APP) == 0) {
5582 sendNow = true;
5583 // Purge entry from pending broadcast list if another one exists already
5584 // since we are sending one right away.
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005585 mPendingBroadcasts.remove(packageName);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005586 } else {
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005587 if (newPackage) {
5588 mPendingBroadcasts.put(packageName, components);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005589 }
5590 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
5591 // Schedule a message
5592 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
5593 }
5594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 }
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 long callingId = Binder.clearCallingIdentity();
5598 try {
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005599 if (sendNow) {
5600 sendPackageChangedBroadcast(packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005601 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005602 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 } finally {
5604 Binder.restoreCallingIdentity(callingId);
5605 }
5606 }
5607
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005608 private void sendPackageChangedBroadcast(String packageName,
Dianne Hackborn86a72da2009-11-11 20:12:41 -08005609 boolean killFlag, ArrayList<String> componentNames, int packageUid) {
5610 if (false) Log.v(TAG, "Sending package changed: package=" + packageName
5611 + " components=" + componentNames);
5612 Bundle extras = new Bundle(4);
5613 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0));
5614 String nameList[] = new String[componentNames.size()];
5615 componentNames.toArray(nameList);
5616 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005617 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);
5618 extras.putInt(Intent.EXTRA_UID, packageUid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005619 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras);
Suchi Amalapurapu0214e942009-09-02 11:03:18 -07005620 }
5621
Jacek Surazski65e13172009-04-28 15:26:38 +02005622 public String getInstallerPackageName(String packageName) {
5623 synchronized (mPackages) {
5624 PackageSetting pkg = mSettings.mPackages.get(packageName);
5625 if (pkg == null) {
5626 throw new IllegalArgumentException("Unknown package: " + packageName);
5627 }
5628 return pkg.installerPackageName;
5629 }
5630 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 public int getApplicationEnabledSetting(String appPackageName) {
5633 synchronized (mPackages) {
5634 PackageSetting pkg = mSettings.mPackages.get(appPackageName);
5635 if (pkg == null) {
5636 throw new IllegalArgumentException("Unknown package: " + appPackageName);
5637 }
5638 return pkg.enabled;
5639 }
5640 }
5641
5642 public int getComponentEnabledSetting(ComponentName componentName) {
5643 synchronized (mPackages) {
5644 final String packageNameStr = componentName.getPackageName();
5645 PackageSetting pkg = mSettings.mPackages.get(packageNameStr);
5646 if (pkg == null) {
5647 throw new IllegalArgumentException("Unknown component: " + componentName);
5648 }
5649 final String classNameStr = componentName.getClassName();
5650 return pkg.currentEnabledStateLP(classNameStr);
5651 }
5652 }
5653
5654 public void enterSafeMode() {
5655 if (!mSystemReady) {
5656 mSafeMode = true;
5657 }
5658 }
5659
5660 public void systemReady() {
5661 mSystemReady = true;
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005662
5663 // Read the compatibilty setting when the system is ready.
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005664 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005665 mContext.getContentResolver(),
5666 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005667 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005668 if (DEBUG_SETTINGS) {
Mitsuru Oshima69fff4a2009-07-21 09:51:05 -07005669 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
Mitsuru Oshimae5fb3282009-06-09 21:16:08 -07005670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 }
5672
5673 public boolean isSafeMode() {
5674 return mSafeMode;
5675 }
5676
5677 public boolean hasSystemUidErrors() {
5678 return mHasSystemUidErrors;
5679 }
5680
5681 static String arrayToString(int[] array) {
5682 StringBuffer buf = new StringBuffer(128);
5683 buf.append('[');
5684 if (array != null) {
5685 for (int i=0; i<array.length; i++) {
5686 if (i > 0) buf.append(", ");
5687 buf.append(array[i]);
5688 }
5689 }
5690 buf.append(']');
5691 return buf.toString();
5692 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 @Override
5695 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5696 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
5697 != PackageManager.PERMISSION_GRANTED) {
5698 pw.println("Permission Denial: can't dump ActivityManager from from pid="
5699 + Binder.getCallingPid()
5700 + ", uid=" + Binder.getCallingUid()
5701 + " without permission "
5702 + android.Manifest.permission.DUMP);
5703 return;
5704 }
5705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005706 synchronized (mPackages) {
5707 pw.println("Activity Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005708 mActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 pw.println(" ");
5710 pw.println("Receiver Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005711 mReceivers.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 pw.println(" ");
5713 pw.println("Service Resolver Table:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005714 mServices.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005715 pw.println(" ");
5716 pw.println("Preferred Activities:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005717 mSettings.mPreferredActivities.dump(pw, " ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 pw.println(" ");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005719 pw.println("Permissions:");
5720 {
5721 for (BasePermission p : mSettings.mPermissions.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005722 pw.print(" Permission ["); pw.print(p.name); pw.print("] (");
5723 pw.print(Integer.toHexString(System.identityHashCode(p)));
5724 pw.println("):");
5725 pw.print(" sourcePackage="); pw.println(p.sourcePackage);
5726 pw.print(" uid="); pw.print(p.uid);
5727 pw.print(" gids="); pw.print(arrayToString(p.gids));
5728 pw.print(" type="); pw.println(p.type);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005729 }
5730 }
5731 pw.println(" ");
5732 pw.println("Packages:");
5733 {
5734 for (PackageSetting ps : mSettings.mPackages.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005735 pw.print(" Package ["); pw.print(ps.name); pw.print("] (");
5736 pw.print(Integer.toHexString(System.identityHashCode(ps)));
5737 pw.println("):");
5738 pw.print(" userId="); pw.print(ps.userId);
5739 pw.print(" gids="); pw.println(arrayToString(ps.gids));
5740 pw.print(" sharedUser="); pw.println(ps.sharedUser);
5741 pw.print(" pkg="); pw.println(ps.pkg);
5742 pw.print(" codePath="); pw.println(ps.codePathString);
5743 pw.print(" resourcePath="); pw.println(ps.resourcePathString);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005744 if (ps.pkg != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005745 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005746 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005747 pw.print(" supportsScreens=[");
5748 boolean first = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005749 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005750 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005751 if (!first) pw.print(", ");
5752 first = false;
5753 pw.print("medium");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005754 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005755 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005756 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005757 if (!first) pw.print(", ");
5758 first = false;
5759 pw.print("large");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005760 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005761 if ((ps.pkg.applicationInfo.flags &
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005762 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005763 if (!first) pw.print(", ");
5764 first = false;
5765 pw.print("small");
Mitsuru Oshima841f13c2009-07-17 17:23:31 -07005766 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005767 if ((ps.pkg.applicationInfo.flags &
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005768 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005769 if (!first) pw.print(", ");
5770 first = false;
5771 pw.print("resizeable");
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005773 if ((ps.pkg.applicationInfo.flags &
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005774 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
5775 if (!first) pw.print(", ");
5776 first = false;
5777 pw.print("anyDensity");
5778 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005779 }
Dianne Hackborn11b822d2009-07-21 20:03:02 -07005780 pw.println("]");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005781 pw.print(" timeStamp="); pw.println(ps.getTimeStampStr());
5782 pw.print(" signatures="); pw.println(ps.signatures);
5783 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
5784 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
5785 pw.print(" installStatus="); pw.print(ps.installStatus);
5786 pw.print(" enabled="); pw.println(ps.enabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005787 if (ps.disabledComponents.size() > 0) {
5788 pw.println(" disabledComponents:");
5789 for (String s : ps.disabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005790 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005791 }
5792 }
5793 if (ps.enabledComponents.size() > 0) {
5794 pw.println(" enabledComponents:");
5795 for (String s : ps.enabledComponents) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005796 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005797 }
5798 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005799 if (ps.grantedPermissions.size() > 0) {
5800 pw.println(" grantedPermissions:");
5801 for (String s : ps.grantedPermissions) {
5802 pw.print(" "); pw.println(s);
5803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005804 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005805 if (ps.loadedPermissions.size() > 0) {
5806 pw.println(" loadedPermissions:");
5807 for (String s : ps.loadedPermissions) {
5808 pw.print(" "); pw.println(s);
5809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 }
5811 }
5812 }
5813 pw.println(" ");
5814 pw.println("Shared Users:");
5815 {
5816 for (SharedUserSetting su : mSettings.mSharedUsers.values()) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005817 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] (");
5818 pw.print(Integer.toHexString(System.identityHashCode(su)));
5819 pw.println("):");
5820 pw.print(" userId="); pw.print(su.userId);
5821 pw.print(" gids="); pw.println(arrayToString(su.gids));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 pw.println(" grantedPermissions:");
5823 for (String s : su.grantedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005824 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005825 }
5826 pw.println(" loadedPermissions:");
5827 for (String s : su.loadedPermissions) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07005828 pw.print(" "); pw.println(s);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005829 }
5830 }
5831 }
5832 pw.println(" ");
5833 pw.println("Settings parse messages:");
5834 pw.println(mSettings.mReadMessages.toString());
5835 }
Jeff Hamilton5bfc64f2009-08-18 12:25:30 -05005836
5837 synchronized (mProviders) {
5838 pw.println(" ");
5839 pw.println("Registered ContentProviders:");
5840 for (PackageParser.Provider p : mProviders.values()) {
5841 pw.println(" ["); pw.println(p.info.authority); pw.println("]: ");
5842 pw.println(p.toString());
5843 }
5844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 }
5846
5847 static final class BasePermission {
5848 final static int TYPE_NORMAL = 0;
5849 final static int TYPE_BUILTIN = 1;
5850 final static int TYPE_DYNAMIC = 2;
5851
5852 final String name;
5853 final String sourcePackage;
5854 final int type;
5855 PackageParser.Permission perm;
5856 PermissionInfo pendingInfo;
5857 int uid;
5858 int[] gids;
5859
5860 BasePermission(String _name, String _sourcePackage, int _type) {
5861 name = _name;
5862 sourcePackage = _sourcePackage;
5863 type = _type;
5864 }
5865 }
5866
5867 static class PackageSignatures {
5868 private Signature[] mSignatures;
5869
5870 PackageSignatures(Signature[] sigs) {
5871 assignSignatures(sigs);
5872 }
5873
5874 PackageSignatures() {
5875 }
5876
5877 void writeXml(XmlSerializer serializer, String tagName,
5878 ArrayList<Signature> pastSignatures) throws IOException {
5879 if (mSignatures == null) {
5880 return;
5881 }
5882 serializer.startTag(null, tagName);
5883 serializer.attribute(null, "count",
5884 Integer.toString(mSignatures.length));
5885 for (int i=0; i<mSignatures.length; i++) {
5886 serializer.startTag(null, "cert");
5887 final Signature sig = mSignatures[i];
5888 final int sigHash = sig.hashCode();
5889 final int numPast = pastSignatures.size();
5890 int j;
5891 for (j=0; j<numPast; j++) {
5892 Signature pastSig = pastSignatures.get(j);
5893 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
5894 serializer.attribute(null, "index", Integer.toString(j));
5895 break;
5896 }
5897 }
5898 if (j >= numPast) {
5899 pastSignatures.add(sig);
5900 serializer.attribute(null, "index", Integer.toString(numPast));
5901 serializer.attribute(null, "key", sig.toCharsString());
5902 }
5903 serializer.endTag(null, "cert");
5904 }
5905 serializer.endTag(null, tagName);
5906 }
5907
5908 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
5909 throws IOException, XmlPullParserException {
5910 String countStr = parser.getAttributeValue(null, "count");
5911 if (countStr == null) {
5912 reportSettingsProblem(Log.WARN,
5913 "Error in package manager settings: <signatures> has"
5914 + " no count at " + parser.getPositionDescription());
5915 XmlUtils.skipCurrentTag(parser);
5916 }
5917 final int count = Integer.parseInt(countStr);
5918 mSignatures = new Signature[count];
5919 int pos = 0;
5920
5921 int outerDepth = parser.getDepth();
5922 int type;
5923 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
5924 && (type != XmlPullParser.END_TAG
5925 || parser.getDepth() > outerDepth)) {
5926 if (type == XmlPullParser.END_TAG
5927 || type == XmlPullParser.TEXT) {
5928 continue;
5929 }
5930
5931 String tagName = parser.getName();
5932 if (tagName.equals("cert")) {
5933 if (pos < count) {
5934 String index = parser.getAttributeValue(null, "index");
5935 if (index != null) {
5936 try {
5937 int idx = Integer.parseInt(index);
5938 String key = parser.getAttributeValue(null, "key");
5939 if (key == null) {
5940 if (idx >= 0 && idx < pastSignatures.size()) {
5941 Signature sig = pastSignatures.get(idx);
5942 if (sig != null) {
5943 mSignatures[pos] = pastSignatures.get(idx);
5944 pos++;
5945 } else {
5946 reportSettingsProblem(Log.WARN,
5947 "Error in package manager settings: <cert> "
5948 + "index " + index + " is not defined at "
5949 + parser.getPositionDescription());
5950 }
5951 } else {
5952 reportSettingsProblem(Log.WARN,
5953 "Error in package manager settings: <cert> "
5954 + "index " + index + " is out of bounds at "
5955 + parser.getPositionDescription());
5956 }
5957 } else {
5958 while (pastSignatures.size() <= idx) {
5959 pastSignatures.add(null);
5960 }
5961 Signature sig = new Signature(key);
5962 pastSignatures.set(idx, sig);
5963 mSignatures[pos] = sig;
5964 pos++;
5965 }
5966 } catch (NumberFormatException e) {
5967 reportSettingsProblem(Log.WARN,
5968 "Error in package manager settings: <cert> "
5969 + "index " + index + " is not a number at "
5970 + parser.getPositionDescription());
5971 }
5972 } else {
5973 reportSettingsProblem(Log.WARN,
5974 "Error in package manager settings: <cert> has"
5975 + " no index at " + parser.getPositionDescription());
5976 }
5977 } else {
5978 reportSettingsProblem(Log.WARN,
5979 "Error in package manager settings: too "
5980 + "many <cert> tags, expected " + count
5981 + " at " + parser.getPositionDescription());
5982 }
5983 } else {
5984 reportSettingsProblem(Log.WARN,
5985 "Unknown element under <cert>: "
5986 + parser.getName());
5987 }
5988 XmlUtils.skipCurrentTag(parser);
5989 }
5990
5991 if (pos < count) {
5992 // Should never happen -- there is an error in the written
5993 // settings -- but if it does we don't want to generate
5994 // a bad array.
5995 Signature[] newSigs = new Signature[pos];
5996 System.arraycopy(mSignatures, 0, newSigs, 0, pos);
5997 mSignatures = newSigs;
5998 }
5999 }
6000
6001 /**
6002 * If any of the given 'sigs' is contained in the existing signatures,
6003 * then completely replace the current signatures with the ones in
6004 * 'sigs'. This is used for updating an existing package to a newly
6005 * installed version.
6006 */
6007 boolean updateSignatures(Signature[] sigs, boolean update) {
6008 if (mSignatures == null) {
6009 if (update) {
6010 assignSignatures(sigs);
6011 }
6012 return true;
6013 }
6014 if (sigs == null) {
6015 return false;
6016 }
6017
6018 for (int i=0; i<sigs.length; i++) {
6019 Signature sig = sigs[i];
6020 for (int j=0; j<mSignatures.length; j++) {
6021 if (mSignatures[j].equals(sig)) {
6022 if (update) {
6023 assignSignatures(sigs);
6024 }
6025 return true;
6026 }
6027 }
6028 }
6029 return false;
6030 }
6031
6032 /**
6033 * If any of the given 'sigs' is contained in the existing signatures,
6034 * then add in any new signatures found in 'sigs'. This is used for
6035 * including a new package into an existing shared user id.
6036 */
6037 boolean mergeSignatures(Signature[] sigs, boolean update) {
6038 if (mSignatures == null) {
6039 if (update) {
6040 assignSignatures(sigs);
6041 }
6042 return true;
6043 }
6044 if (sigs == null) {
6045 return false;
6046 }
6047
6048 Signature[] added = null;
6049 int addedCount = 0;
6050 boolean haveMatch = false;
6051 for (int i=0; i<sigs.length; i++) {
6052 Signature sig = sigs[i];
6053 boolean found = false;
6054 for (int j=0; j<mSignatures.length; j++) {
6055 if (mSignatures[j].equals(sig)) {
6056 found = true;
6057 haveMatch = true;
6058 break;
6059 }
6060 }
6061
6062 if (!found) {
6063 if (added == null) {
6064 added = new Signature[sigs.length];
6065 }
6066 added[i] = sig;
6067 addedCount++;
6068 }
6069 }
6070
6071 if (!haveMatch) {
6072 // Nothing matched -- reject the new signatures.
6073 return false;
6074 }
6075 if (added == null) {
6076 // Completely matched -- nothing else to do.
6077 return true;
6078 }
6079
6080 // Add additional signatures in.
6081 if (update) {
6082 Signature[] total = new Signature[addedCount+mSignatures.length];
6083 System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
6084 int j = mSignatures.length;
6085 for (int i=0; i<added.length; i++) {
6086 if (added[i] != null) {
6087 total[j] = added[i];
6088 j++;
6089 }
6090 }
6091 mSignatures = total;
6092 }
6093 return true;
6094 }
6095
6096 private void assignSignatures(Signature[] sigs) {
6097 if (sigs == null) {
6098 mSignatures = null;
6099 return;
6100 }
6101 mSignatures = new Signature[sigs.length];
6102 for (int i=0; i<sigs.length; i++) {
6103 mSignatures[i] = sigs[i];
6104 }
6105 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006107 @Override
6108 public String toString() {
6109 StringBuffer buf = new StringBuffer(128);
6110 buf.append("PackageSignatures{");
6111 buf.append(Integer.toHexString(System.identityHashCode(this)));
6112 buf.append(" [");
6113 if (mSignatures != null) {
6114 for (int i=0; i<mSignatures.length; i++) {
6115 if (i > 0) buf.append(", ");
6116 buf.append(Integer.toHexString(
6117 System.identityHashCode(mSignatures[i])));
6118 }
6119 }
6120 buf.append("]}");
6121 return buf.toString();
6122 }
6123 }
6124
6125 static class PreferredActivity extends IntentFilter {
6126 final int mMatch;
6127 final String[] mSetPackages;
6128 final String[] mSetClasses;
6129 final String[] mSetComponents;
6130 final ComponentName mActivity;
6131 final String mShortActivity;
6132 String mParseError;
6133
6134 PreferredActivity(IntentFilter filter, int match, ComponentName[] set,
6135 ComponentName activity) {
6136 super(filter);
6137 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK;
6138 mActivity = activity;
6139 mShortActivity = activity.flattenToShortString();
6140 mParseError = null;
6141 if (set != null) {
6142 final int N = set.length;
6143 String[] myPackages = new String[N];
6144 String[] myClasses = new String[N];
6145 String[] myComponents = new String[N];
6146 for (int i=0; i<N; i++) {
6147 ComponentName cn = set[i];
6148 if (cn == null) {
6149 mSetPackages = null;
6150 mSetClasses = null;
6151 mSetComponents = null;
6152 return;
6153 }
6154 myPackages[i] = cn.getPackageName().intern();
6155 myClasses[i] = cn.getClassName().intern();
6156 myComponents[i] = cn.flattenToShortString().intern();
6157 }
6158 mSetPackages = myPackages;
6159 mSetClasses = myClasses;
6160 mSetComponents = myComponents;
6161 } else {
6162 mSetPackages = null;
6163 mSetClasses = null;
6164 mSetComponents = null;
6165 }
6166 }
6167
6168 PreferredActivity(XmlPullParser parser) throws XmlPullParserException,
6169 IOException {
6170 mShortActivity = parser.getAttributeValue(null, "name");
6171 mActivity = ComponentName.unflattenFromString(mShortActivity);
6172 if (mActivity == null) {
6173 mParseError = "Bad activity name " + mShortActivity;
6174 }
6175 String matchStr = parser.getAttributeValue(null, "match");
6176 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0;
6177 String setCountStr = parser.getAttributeValue(null, "set");
6178 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0;
6179
6180 String[] myPackages = setCount > 0 ? new String[setCount] : null;
6181 String[] myClasses = setCount > 0 ? new String[setCount] : null;
6182 String[] myComponents = setCount > 0 ? new String[setCount] : null;
6183
6184 int setPos = 0;
6185
6186 int outerDepth = parser.getDepth();
6187 int type;
6188 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
6189 && (type != XmlPullParser.END_TAG
6190 || parser.getDepth() > outerDepth)) {
6191 if (type == XmlPullParser.END_TAG
6192 || type == XmlPullParser.TEXT) {
6193 continue;
6194 }
6195
6196 String tagName = parser.getName();
6197 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth="
6198 // + parser.getDepth() + " tag=" + tagName);
6199 if (tagName.equals("set")) {
6200 String name = parser.getAttributeValue(null, "name");
6201 if (name == null) {
6202 if (mParseError == null) {
6203 mParseError = "No name in set tag in preferred activity "
6204 + mShortActivity;
6205 }
6206 } else if (setPos >= setCount) {
6207 if (mParseError == null) {
6208 mParseError = "Too many set tags in preferred activity "
6209 + mShortActivity;
6210 }
6211 } else {
6212 ComponentName cn = ComponentName.unflattenFromString(name);
6213 if (cn == null) {
6214 if (mParseError == null) {
6215 mParseError = "Bad set name " + name + " in preferred activity "
6216 + mShortActivity;
6217 }
6218 } else {
6219 myPackages[setPos] = cn.getPackageName();
6220 myClasses[setPos] = cn.getClassName();
6221 myComponents[setPos] = name;
6222 setPos++;
6223 }
6224 }
6225 XmlUtils.skipCurrentTag(parser);
6226 } else if (tagName.equals("filter")) {
6227 //Log.i(TAG, "Starting to parse filter...");
6228 readFromXml(parser);
6229 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth="
6230 // + parser.getDepth() + " tag=" + parser.getName());
6231 } else {
6232 reportSettingsProblem(Log.WARN,
6233 "Unknown element under <preferred-activities>: "
6234 + parser.getName());
6235 XmlUtils.skipCurrentTag(parser);
6236 }
6237 }
6238
6239 if (setPos != setCount) {
6240 if (mParseError == null) {
6241 mParseError = "Not enough set tags (expected " + setCount
6242 + " but found " + setPos + ") in " + mShortActivity;
6243 }
6244 }
6245
6246 mSetPackages = myPackages;
6247 mSetClasses = myClasses;
6248 mSetComponents = myComponents;
6249 }
6250
6251 public void writeToXml(XmlSerializer serializer) throws IOException {
6252 final int NS = mSetClasses != null ? mSetClasses.length : 0;
6253 serializer.attribute(null, "name", mShortActivity);
6254 serializer.attribute(null, "match", Integer.toHexString(mMatch));
6255 serializer.attribute(null, "set", Integer.toString(NS));
6256 for (int s=0; s<NS; s++) {
6257 serializer.startTag(null, "set");
6258 serializer.attribute(null, "name", mSetComponents[s]);
6259 serializer.endTag(null, "set");
6260 }
6261 serializer.startTag(null, "filter");
6262 super.writeToXml(serializer);
6263 serializer.endTag(null, "filter");
6264 }
6265
6266 boolean sameSet(List<ResolveInfo> query, int priority) {
6267 if (mSetPackages == null) return false;
6268 final int NQ = query.size();
6269 final int NS = mSetPackages.length;
6270 int numMatch = 0;
6271 for (int i=0; i<NQ; i++) {
6272 ResolveInfo ri = query.get(i);
6273 if (ri.priority != priority) continue;
6274 ActivityInfo ai = ri.activityInfo;
6275 boolean good = false;
6276 for (int j=0; j<NS; j++) {
6277 if (mSetPackages[j].equals(ai.packageName)
6278 && mSetClasses[j].equals(ai.name)) {
6279 numMatch++;
6280 good = true;
6281 break;
6282 }
6283 }
6284 if (!good) return false;
6285 }
6286 return numMatch == NS;
6287 }
6288 }
6289
6290 static class GrantedPermissions {
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006291 int pkgFlags;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006293 HashSet<String> grantedPermissions = new HashSet<String>();
6294 int[] gids;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006296 HashSet<String> loadedPermissions = new HashSet<String>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 GrantedPermissions(int pkgFlags) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08006299 this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
6300 (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
6301 (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006302 }
6303 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006305 /**
6306 * Settings base class for pending and resolved classes.
6307 */
6308 static class PackageSettingBase extends GrantedPermissions {
6309 final String name;
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006310 File codePath;
6311 String codePathString;
6312 File resourcePath;
6313 String resourcePathString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006314 private long timeStamp;
6315 private String timeStampString = "0";
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006316 int versionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006317
6318 PackageSignatures signatures = new PackageSignatures();
6319
6320 boolean permissionsFixed;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006322 /* Explicitly disabled components */
6323 HashSet<String> disabledComponents = new HashSet<String>(0);
6324 /* Explicitly enabled components */
6325 HashSet<String> enabledComponents = new HashSet<String>(0);
6326 int enabled = COMPONENT_ENABLED_STATE_DEFAULT;
6327 int installStatus = PKG_INSTALL_COMPLETE;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006328
Jacek Surazski65e13172009-04-28 15:26:38 +02006329 /* package name of the app that installed this package */
6330 String installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331
6332 PackageSettingBase(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006333 int pVersionCode, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 super(pkgFlags);
6335 this.name = name;
6336 this.codePath = codePath;
6337 this.codePathString = codePath.toString();
6338 this.resourcePath = resourcePath;
6339 this.resourcePathString = resourcePath.toString();
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006340 this.versionCode = pVersionCode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 }
6342
Jacek Surazski65e13172009-04-28 15:26:38 +02006343 public void setInstallerPackageName(String packageName) {
6344 installerPackageName = packageName;
6345 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006346
Jacek Surazski65e13172009-04-28 15:26:38 +02006347 String getInstallerPackageName() {
6348 return installerPackageName;
6349 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 public void setInstallStatus(int newStatus) {
6352 installStatus = newStatus;
6353 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006355 public int getInstallStatus() {
6356 return installStatus;
6357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 public void setTimeStamp(long newStamp) {
6360 if (newStamp != timeStamp) {
6361 timeStamp = newStamp;
6362 timeStampString = Long.toString(newStamp);
6363 }
6364 }
6365
6366 public void setTimeStamp(long newStamp, String newStampStr) {
6367 timeStamp = newStamp;
6368 timeStampString = newStampStr;
6369 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006371 public long getTimeStamp() {
6372 return timeStamp;
6373 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 public String getTimeStampStr() {
6376 return timeStampString;
6377 }
6378
6379 public void copyFrom(PackageSettingBase base) {
6380 grantedPermissions = base.grantedPermissions;
6381 gids = base.gids;
6382 loadedPermissions = base.loadedPermissions;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 timeStamp = base.timeStamp;
6385 timeStampString = base.timeStampString;
6386 signatures = base.signatures;
6387 permissionsFixed = base.permissionsFixed;
6388 disabledComponents = base.disabledComponents;
6389 enabledComponents = base.enabledComponents;
6390 enabled = base.enabled;
6391 installStatus = base.installStatus;
6392 }
6393
6394 void enableComponentLP(String componentClassName) {
6395 disabledComponents.remove(componentClassName);
6396 enabledComponents.add(componentClassName);
6397 }
6398
6399 void disableComponentLP(String componentClassName) {
6400 enabledComponents.remove(componentClassName);
6401 disabledComponents.add(componentClassName);
6402 }
6403
6404 void restoreComponentLP(String componentClassName) {
6405 enabledComponents.remove(componentClassName);
6406 disabledComponents.remove(componentClassName);
6407 }
6408
6409 int currentEnabledStateLP(String componentName) {
6410 if (enabledComponents.contains(componentName)) {
6411 return COMPONENT_ENABLED_STATE_ENABLED;
6412 } else if (disabledComponents.contains(componentName)) {
6413 return COMPONENT_ENABLED_STATE_DISABLED;
6414 } else {
6415 return COMPONENT_ENABLED_STATE_DEFAULT;
6416 }
6417 }
6418 }
6419
6420 /**
6421 * Settings data for a particular package we know about.
6422 */
6423 static final class PackageSetting extends PackageSettingBase {
6424 int userId;
6425 PackageParser.Package pkg;
6426 SharedUserSetting sharedUser;
6427
6428 PackageSetting(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006429 int pVersionCode, int pkgFlags) {
6430 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006431 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006433 @Override
6434 public String toString() {
6435 return "PackageSetting{"
6436 + Integer.toHexString(System.identityHashCode(this))
6437 + " " + name + "/" + userId + "}";
6438 }
6439 }
6440
6441 /**
6442 * Settings data for a particular shared user ID we know about.
6443 */
6444 static final class SharedUserSetting extends GrantedPermissions {
6445 final String name;
6446 int userId;
6447 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>();
6448 final PackageSignatures signatures = new PackageSignatures();
6449
6450 SharedUserSetting(String _name, int _pkgFlags) {
6451 super(_pkgFlags);
6452 name = _name;
6453 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 @Override
6456 public String toString() {
6457 return "SharedUserSetting{"
6458 + Integer.toHexString(System.identityHashCode(this))
6459 + " " + name + "/" + userId + "}";
6460 }
6461 }
6462
6463 /**
6464 * Holds information about dynamic settings.
6465 */
6466 private static final class Settings {
6467 private final File mSettingsFilename;
6468 private final File mBackupSettingsFilename;
6469 private final HashMap<String, PackageSetting> mPackages =
6470 new HashMap<String, PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 // List of replaced system applications
6472 final HashMap<String, PackageSetting> mDisabledSysPackages =
6473 new HashMap<String, PackageSetting>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006475 // The user's preferred activities associated with particular intent
6476 // filters.
6477 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities =
6478 new IntentResolver<PreferredActivity, PreferredActivity>() {
6479 @Override
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006480 protected void dumpFilter(PrintWriter out, String prefix,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 PreferredActivity filter) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006482 out.print(prefix); out.print(
6483 Integer.toHexString(System.identityHashCode(filter)));
6484 out.print(' ');
6485 out.print(filter.mActivity.flattenToShortString());
6486 out.print(" match=0x");
6487 out.println( Integer.toHexString(filter.mMatch));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 if (filter.mSetComponents != null) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006489 out.print(prefix); out.println(" Selected from:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006490 for (int i=0; i<filter.mSetComponents.length; i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006491 out.print(prefix); out.print(" ");
6492 out.println(filter.mSetComponents[i]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 }
6494 }
6495 }
6496 };
6497 private final HashMap<String, SharedUserSetting> mSharedUsers =
6498 new HashMap<String, SharedUserSetting>();
6499 private final ArrayList<Object> mUserIds = new ArrayList<Object>();
6500 private final SparseArray<Object> mOtherUserIds =
6501 new SparseArray<Object>();
6502
6503 // For reading/writing settings file.
6504 private final ArrayList<Signature> mPastSignatures =
6505 new ArrayList<Signature>();
6506
6507 // Mapping from permission names to info about them.
6508 final HashMap<String, BasePermission> mPermissions =
6509 new HashMap<String, BasePermission>();
6510
6511 // Mapping from permission tree names to info about them.
6512 final HashMap<String, BasePermission> mPermissionTrees =
6513 new HashMap<String, BasePermission>();
6514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006515 private final StringBuilder mReadMessages = new StringBuilder();
6516
6517 private static final class PendingPackage extends PackageSettingBase {
6518 final int sharedId;
6519
6520 PendingPackage(String name, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006521 int sharedId, int pVersionCode, int pkgFlags) {
6522 super(name, codePath, resourcePath, pVersionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 this.sharedId = sharedId;
6524 }
6525 }
6526 private final ArrayList<PendingPackage> mPendingPackages
6527 = new ArrayList<PendingPackage>();
6528
6529 Settings() {
6530 File dataDir = Environment.getDataDirectory();
6531 File systemDir = new File(dataDir, "system");
Oscar Montemayora8529f62009-11-18 10:14:20 -08006532 // TODO(oam): This secure dir creation needs to be moved somewhere else (later)
6533 File systemSecureDir = new File(dataDir, "secure/system");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 systemDir.mkdirs();
Oscar Montemayora8529f62009-11-18 10:14:20 -08006535 systemSecureDir.mkdirs();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 FileUtils.setPermissions(systemDir.toString(),
6537 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6538 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6539 -1, -1);
Oscar Montemayora8529f62009-11-18 10:14:20 -08006540 FileUtils.setPermissions(systemSecureDir.toString(),
6541 FileUtils.S_IRWXU|FileUtils.S_IRWXG
6542 |FileUtils.S_IROTH|FileUtils.S_IXOTH,
6543 -1, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 mSettingsFilename = new File(systemDir, "packages.xml");
6545 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
6546 }
6547
6548 PackageSetting getPackageLP(PackageParser.Package pkg,
6549 SharedUserSetting sharedUser, File codePath, File resourcePath,
6550 int pkgFlags, boolean create, boolean add) {
6551 final String name = pkg.packageName;
6552 PackageSetting p = getPackageLP(name, sharedUser, codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006553 resourcePath, pkg.mVersionCode, pkgFlags, create, add);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006554 return p;
6555 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006556
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006557 PackageSetting peekPackageLP(String name) {
6558 return mPackages.get(name);
6559 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006560 PackageSetting p = mPackages.get(name);
6561 if (p != null && p.codePath.getPath().equals(codePath)) {
6562 return p;
6563 }
6564 return null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006565 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006566 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 void setInstallStatus(String pkgName, int status) {
6569 PackageSetting p = mPackages.get(pkgName);
6570 if(p != null) {
6571 if(p.getInstallStatus() != status) {
6572 p.setInstallStatus(status);
6573 }
6574 }
6575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006576
Jacek Surazski65e13172009-04-28 15:26:38 +02006577 void setInstallerPackageName(String pkgName,
6578 String installerPkgName) {
6579 PackageSetting p = mPackages.get(pkgName);
6580 if(p != null) {
6581 p.setInstallerPackageName(installerPkgName);
6582 }
6583 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006584
Jacek Surazski65e13172009-04-28 15:26:38 +02006585 String getInstallerPackageName(String pkgName) {
6586 PackageSetting p = mPackages.get(pkgName);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006587 return (p == null) ? null : p.getInstallerPackageName();
Jacek Surazski65e13172009-04-28 15:26:38 +02006588 }
6589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006590 int getInstallStatus(String pkgName) {
6591 PackageSetting p = mPackages.get(pkgName);
6592 if(p != null) {
6593 return p.getInstallStatus();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006595 return -1;
6596 }
6597
6598 SharedUserSetting getSharedUserLP(String name,
6599 int pkgFlags, boolean create) {
6600 SharedUserSetting s = mSharedUsers.get(name);
6601 if (s == null) {
6602 if (!create) {
6603 return null;
6604 }
6605 s = new SharedUserSetting(name, pkgFlags);
6606 if (MULTIPLE_APPLICATION_UIDS) {
6607 s.userId = newUserIdLP(s);
6608 } else {
6609 s.userId = FIRST_APPLICATION_UID;
6610 }
6611 Log.i(TAG, "New shared user " + name + ": id=" + s.userId);
6612 // < 0 means we couldn't assign a userid; fall out and return
6613 // s, which is currently null
6614 if (s.userId >= 0) {
6615 mSharedUsers.put(name, s);
6616 }
6617 }
6618
6619 return s;
6620 }
6621
6622 int disableSystemPackageLP(String name) {
6623 PackageSetting p = mPackages.get(name);
6624 if(p == null) {
6625 Log.w(TAG, "Package:"+name+" is not an installed package");
6626 return -1;
6627 }
6628 PackageSetting dp = mDisabledSysPackages.get(name);
6629 // always make sure the system package code and resource paths dont change
6630 if(dp == null) {
6631 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6632 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6633 }
6634 mDisabledSysPackages.put(name, p);
6635 }
6636 return removePackageLP(name);
6637 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 PackageSetting enableSystemPackageLP(String name) {
6640 PackageSetting p = mDisabledSysPackages.get(name);
6641 if(p == null) {
6642 Log.w(TAG, "Package:"+name+" is not disabled");
6643 return null;
6644 }
6645 // Reset flag in ApplicationInfo object
6646 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
6647 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
6648 }
6649 PackageSetting ret = addPackageLP(name, p.codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006650 p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 mDisabledSysPackages.remove(name);
6652 return ret;
6653 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 PackageSetting addPackageLP(String name, File codePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006656 File resourcePath, int uid, int vc, int pkgFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006657 PackageSetting p = mPackages.get(name);
6658 if (p != null) {
6659 if (p.userId == uid) {
6660 return p;
6661 }
6662 reportSettingsProblem(Log.ERROR,
6663 "Adding duplicate package, keeping first: " + name);
6664 return null;
6665 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006666 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006667 p.userId = uid;
6668 if (addUserIdLP(uid, p, name)) {
6669 mPackages.put(name, p);
6670 return p;
6671 }
6672 return null;
6673 }
6674
6675 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) {
6676 SharedUserSetting s = mSharedUsers.get(name);
6677 if (s != null) {
6678 if (s.userId == uid) {
6679 return s;
6680 }
6681 reportSettingsProblem(Log.ERROR,
6682 "Adding duplicate shared user, keeping first: " + name);
6683 return null;
6684 }
6685 s = new SharedUserSetting(name, pkgFlags);
6686 s.userId = uid;
6687 if (addUserIdLP(uid, s, name)) {
6688 mSharedUsers.put(name, s);
6689 return s;
6690 }
6691 return null;
6692 }
6693
6694 private PackageSetting getPackageLP(String name,
6695 SharedUserSetting sharedUser, File codePath, File resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006696 int vc, int pkgFlags, boolean create, boolean add) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006697 PackageSetting p = mPackages.get(name);
6698 if (p != null) {
6699 if (!p.codePath.equals(codePath)) {
6700 // Check to see if its a disabled system app
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006701 if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006702 // This is an updated system app with versions in both system
6703 // and data partition. Just let the most recent version
6704 // take precedence.
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006705 Log.w(TAG, "Trying to update system app code path from " +
6706 p.codePathString + " to " + codePath.toString());
Suchi Amalapurapuea5c0442009-07-13 10:36:15 -07006707 } else {
Suchi Amalapurapub24a9672009-07-01 14:04:43 -07006708 // Let the app continue with previous uid if code path changes.
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -07006709 reportSettingsProblem(Log.WARN,
6710 "Package " + name + " codePath changed from " + p.codePath
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006711 + " to " + codePath + "; Retaining data and using new");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 }
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006713 }
6714 if (p.sharedUser != sharedUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 reportSettingsProblem(Log.WARN,
6716 "Package " + name + " shared user changed from "
6717 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
6718 + " to "
6719 + (sharedUser != null ? sharedUser.name : "<nothing>")
6720 + "; replacing with new");
6721 p = null;
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006722 } else {
6723 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
6724 // If what we are scanning is a system package, then
6725 // make it so, regardless of whether it was previously
6726 // installed only in the data partition.
6727 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
6728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 }
6730 }
6731 if (p == null) {
6732 // Create a new PackageSettings entry. this can end up here because
6733 // of code path mismatch or user id mismatch of an updated system partition
6734 if (!create) {
6735 return null;
6736 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07006737 p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 p.setTimeStamp(codePath.lastModified());
Dianne Hackborn5d6d7732009-05-13 18:09:56 -07006739 p.sharedUser = sharedUser;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006740 if (sharedUser != null) {
6741 p.userId = sharedUser.userId;
6742 } else if (MULTIPLE_APPLICATION_UIDS) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006743 // Clone the setting here for disabled system packages
6744 PackageSetting dis = mDisabledSysPackages.get(name);
6745 if (dis != null) {
6746 // For disabled packages a new setting is created
6747 // from the existing user id. This still has to be
6748 // added to list of user id's
6749 // Copy signatures from previous setting
6750 if (dis.signatures.mSignatures != null) {
6751 p.signatures.mSignatures = dis.signatures.mSignatures.clone();
6752 }
6753 p.userId = dis.userId;
6754 // Clone permissions
6755 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
6756 p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
6757 // Clone component info
6758 p.disabledComponents = new HashSet<String>(dis.disabledComponents);
6759 p.enabledComponents = new HashSet<String>(dis.enabledComponents);
6760 // Add new setting to list of user ids
6761 addUserIdLP(p.userId, p, name);
6762 } else {
6763 // Assign new user id
6764 p.userId = newUserIdLP(p);
6765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006766 } else {
6767 p.userId = FIRST_APPLICATION_UID;
6768 }
6769 if (p.userId < 0) {
6770 reportSettingsProblem(Log.WARN,
6771 "Package " + name + " could not be assigned a valid uid");
6772 return null;
6773 }
6774 if (add) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006775 // Finish adding new package by adding it and updating shared
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006776 // user preferences
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006777 addPackageSettingLP(p, name, sharedUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 }
6779 }
6780 return p;
6781 }
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006782
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006783 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006784 p.pkg = pkg;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006785 String codePath = pkg.applicationInfo.sourceDir;
6786 String resourcePath = pkg.applicationInfo.publicSourceDir;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006787 // Update code path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006788 if (!codePath.equalsIgnoreCase(p.codePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006789 Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006790 " changing from " + p.codePathString + " to " + codePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006791 p.codePath = new File(codePath);
6792 p.codePathString = codePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006793 }
6794 //Update resource path if needed
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006795 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) {
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006796 Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
Dianne Hackborna33e3f72009-09-29 17:28:24 -07006797 " changing from " + p.resourcePathString + " to " + resourcePath);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08006798 p.resourcePath = new File(resourcePath);
6799 p.resourcePathString = resourcePath;
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006800 }
6801 // Update version code if needed
6802 if (pkg.mVersionCode != p.versionCode) {
6803 p.versionCode = pkg.mVersionCode;
6804 }
6805 addPackageSettingLP(p, pkg.packageName, p.sharedUser);
6806 }
6807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006808 // Utility method that adds a PackageSetting to mPackages and
6809 // completes updating the shared user attributes
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006810 private void addPackageSettingLP(PackageSetting p, String name,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006811 SharedUserSetting sharedUser) {
6812 mPackages.put(name, p);
6813 if (sharedUser != null) {
6814 if (p.sharedUser != null && p.sharedUser != sharedUser) {
6815 reportSettingsProblem(Log.ERROR,
6816 "Package " + p.name + " was user "
6817 + p.sharedUser + " but is now " + sharedUser
6818 + "; I am not changing its files so it will probably fail!");
6819 p.sharedUser.packages.remove(p);
6820 } else if (p.userId != sharedUser.userId) {
6821 reportSettingsProblem(Log.ERROR,
6822 "Package " + p.name + " was user id " + p.userId
6823 + " but is now user " + sharedUser
6824 + " with id " + sharedUser.userId
6825 + "; I am not changing its files so it will probably fail!");
6826 }
6827
6828 sharedUser.packages.add(p);
6829 p.sharedUser = sharedUser;
6830 p.userId = sharedUser.userId;
6831 }
6832 }
6833
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006834 /*
6835 * Update the shared user setting when a package using
6836 * specifying the shared user id is removed. The gids
6837 * associated with each permission of the deleted package
6838 * are removed from the shared user's gid list only if its
6839 * not in use by other permissions of packages in the
6840 * shared user setting.
6841 */
6842 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006843 if ( (deletedPs == null) || (deletedPs.pkg == null)) {
6844 Log.i(TAG, "Trying to update info for null package. Just ignoring");
6845 return;
6846 }
6847 // No sharedUserId
6848 if (deletedPs.sharedUser == null) {
6849 return;
6850 }
6851 SharedUserSetting sus = deletedPs.sharedUser;
6852 // Update permissions
6853 for (String eachPerm: deletedPs.pkg.requestedPermissions) {
6854 boolean used = false;
6855 if (!sus.grantedPermissions.contains (eachPerm)) {
6856 continue;
6857 }
6858 for (PackageSetting pkg:sus.packages) {
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006859 if (pkg.pkg != null &&
6860 !pkg.pkg.packageName.equalsIgnoreCase(deletedPs.pkg.packageName) &&
6861 pkg.pkg.requestedPermissions.contains(eachPerm)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006862 used = true;
6863 break;
6864 }
6865 }
6866 if (!used) {
6867 // can safely delete this permission from list
6868 sus.grantedPermissions.remove(eachPerm);
6869 sus.loadedPermissions.remove(eachPerm);
6870 }
6871 }
6872 // Update gids
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006873 int newGids[] = globalGids;
6874 for (String eachPerm : sus.grantedPermissions) {
6875 BasePermission bp = mPermissions.get(eachPerm);
Suchi Amalapurapud83006c2009-10-28 23:39:46 -07006876 if (bp != null) {
6877 newGids = appendInts(newGids, bp.gids);
6878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 }
6880 sus.gids = newGids;
6881 }
Suchi Amalapurapu2ed287b2009-08-05 12:43:00 -07006882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 private int removePackageLP(String name) {
6884 PackageSetting p = mPackages.get(name);
6885 if (p != null) {
6886 mPackages.remove(name);
6887 if (p.sharedUser != null) {
6888 p.sharedUser.packages.remove(p);
6889 if (p.sharedUser.packages.size() == 0) {
6890 mSharedUsers.remove(p.sharedUser.name);
6891 removeUserIdLP(p.sharedUser.userId);
6892 return p.sharedUser.userId;
6893 }
6894 } else {
6895 removeUserIdLP(p.userId);
6896 return p.userId;
6897 }
6898 }
6899 return -1;
6900 }
6901
6902 private boolean addUserIdLP(int uid, Object obj, Object name) {
6903 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
6904 return false;
6905 }
6906
6907 if (uid >= FIRST_APPLICATION_UID) {
6908 int N = mUserIds.size();
6909 final int index = uid - FIRST_APPLICATION_UID;
6910 while (index >= N) {
6911 mUserIds.add(null);
6912 N++;
6913 }
6914 if (mUserIds.get(index) != null) {
6915 reportSettingsProblem(Log.ERROR,
Suchi Amalapurapu261e66a2009-07-27 15:21:34 -07006916 "Adding duplicate user id: " + uid
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006917 + " name=" + name);
6918 return false;
6919 }
6920 mUserIds.set(index, obj);
6921 } else {
6922 if (mOtherUserIds.get(uid) != null) {
6923 reportSettingsProblem(Log.ERROR,
6924 "Adding duplicate shared id: " + uid
6925 + " name=" + name);
6926 return false;
6927 }
6928 mOtherUserIds.put(uid, obj);
6929 }
6930 return true;
6931 }
6932
6933 public Object getUserIdLP(int uid) {
6934 if (uid >= FIRST_APPLICATION_UID) {
6935 int N = mUserIds.size();
6936 final int index = uid - FIRST_APPLICATION_UID;
6937 return index < N ? mUserIds.get(index) : null;
6938 } else {
6939 return mOtherUserIds.get(uid);
6940 }
6941 }
6942
6943 private void removeUserIdLP(int uid) {
6944 if (uid >= FIRST_APPLICATION_UID) {
6945 int N = mUserIds.size();
6946 final int index = uid - FIRST_APPLICATION_UID;
6947 if (index < N) mUserIds.set(index, null);
6948 } else {
6949 mOtherUserIds.remove(uid);
6950 }
6951 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006953 void writeLP() {
6954 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
6955
6956 // Keep the old settings around until we know the new ones have
6957 // been successfully written.
6958 if (mSettingsFilename.exists()) {
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07006959 // Presence of backup settings file indicates that we failed
6960 // to persist settings earlier. So preserve the older
6961 // backup for future reference since the current settings
6962 // might have been corrupted.
6963 if (!mBackupSettingsFilename.exists()) {
6964 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
6965 Log.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot");
6966 return;
6967 }
6968 } else {
6969 Log.w(TAG, "Preserving older settings backup");
Suchi Amalapurapu3d7e8552009-09-17 15:38:20 -07006970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006971 }
6972
6973 mPastSignatures.clear();
6974
6975 try {
6976 FileOutputStream str = new FileOutputStream(mSettingsFilename);
6977
6978 //XmlSerializer serializer = XmlUtils.serializerInstance();
6979 XmlSerializer serializer = new FastXmlSerializer();
6980 serializer.setOutput(str, "utf-8");
6981 serializer.startDocument(null, true);
6982 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
6983
6984 serializer.startTag(null, "packages");
6985
6986 serializer.startTag(null, "permission-trees");
6987 for (BasePermission bp : mPermissionTrees.values()) {
6988 writePermission(serializer, bp);
6989 }
6990 serializer.endTag(null, "permission-trees");
6991
6992 serializer.startTag(null, "permissions");
6993 for (BasePermission bp : mPermissions.values()) {
6994 writePermission(serializer, bp);
6995 }
6996 serializer.endTag(null, "permissions");
6997
6998 for (PackageSetting pkg : mPackages.values()) {
6999 writePackage(serializer, pkg);
7000 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007002 for (PackageSetting pkg : mDisabledSysPackages.values()) {
7003 writeDisabledSysPackage(serializer, pkg);
7004 }
7005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 serializer.startTag(null, "preferred-activities");
7007 for (PreferredActivity pa : mPreferredActivities.filterSet()) {
7008 serializer.startTag(null, "item");
7009 pa.writeToXml(serializer);
7010 serializer.endTag(null, "item");
7011 }
7012 serializer.endTag(null, "preferred-activities");
7013
7014 for (SharedUserSetting usr : mSharedUsers.values()) {
7015 serializer.startTag(null, "shared-user");
7016 serializer.attribute(null, "name", usr.name);
7017 serializer.attribute(null, "userId",
7018 Integer.toString(usr.userId));
7019 usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
7020 serializer.startTag(null, "perms");
7021 for (String name : usr.grantedPermissions) {
7022 serializer.startTag(null, "item");
7023 serializer.attribute(null, "name", name);
7024 serializer.endTag(null, "item");
7025 }
7026 serializer.endTag(null, "perms");
7027 serializer.endTag(null, "shared-user");
7028 }
7029
7030 serializer.endTag(null, "packages");
7031
7032 serializer.endDocument();
7033
7034 str.flush();
7035 str.close();
7036
7037 // New settings successfully written, old ones are no longer
7038 // needed.
7039 mBackupSettingsFilename.delete();
7040 FileUtils.setPermissions(mSettingsFilename.toString(),
7041 FileUtils.S_IRUSR|FileUtils.S_IWUSR
7042 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
7043 |FileUtils.S_IROTH,
7044 -1, -1);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007045 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007046
7047 } catch(XmlPullParserException e) {
7048 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 -08007049 } catch(java.io.IOException e) {
7050 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 -08007051 }
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07007052 // Clean up partially written file
7053 if (mSettingsFilename.exists()) {
7054 if (!mSettingsFilename.delete()) {
7055 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
7056 }
7057 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 //Debug.stopMethodTracing();
7059 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007060
7061 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007062 throws java.io.IOException {
7063 serializer.startTag(null, "updated-package");
7064 serializer.attribute(null, "name", pkg.name);
7065 serializer.attribute(null, "codePath", pkg.codePathString);
7066 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007067 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7069 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7070 }
7071 if (pkg.sharedUser == null) {
7072 serializer.attribute(null, "userId",
7073 Integer.toString(pkg.userId));
7074 } else {
7075 serializer.attribute(null, "sharedUserId",
7076 Integer.toString(pkg.userId));
7077 }
7078 serializer.startTag(null, "perms");
7079 if (pkg.sharedUser == null) {
7080 // If this is a shared user, the permissions will
7081 // be written there. We still need to write an
7082 // empty permissions list so permissionsFixed will
7083 // be set.
7084 for (final String name : pkg.grantedPermissions) {
7085 BasePermission bp = mPermissions.get(name);
7086 if ((bp != null) && (bp.perm != null) && (bp.perm.info != null)) {
7087 // We only need to write signature or system permissions but this wont
7088 // match the semantics of grantedPermissions. So write all permissions.
7089 serializer.startTag(null, "item");
7090 serializer.attribute(null, "name", name);
7091 serializer.endTag(null, "item");
7092 }
7093 }
7094 }
7095 serializer.endTag(null, "perms");
7096 serializer.endTag(null, "updated-package");
7097 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007098
7099 void writePackage(XmlSerializer serializer, final PackageSetting pkg)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 throws java.io.IOException {
7101 serializer.startTag(null, "package");
7102 serializer.attribute(null, "name", pkg.name);
7103 serializer.attribute(null, "codePath", pkg.codePathString);
7104 if (!pkg.resourcePathString.equals(pkg.codePathString)) {
7105 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
7106 }
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007107 serializer.attribute(null, "flags",
7108 Integer.toString(pkg.pkgFlags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007109 serializer.attribute(null, "ts", pkg.getTimeStampStr());
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007110 serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007111 if (pkg.sharedUser == null) {
7112 serializer.attribute(null, "userId",
7113 Integer.toString(pkg.userId));
7114 } else {
7115 serializer.attribute(null, "sharedUserId",
7116 Integer.toString(pkg.userId));
7117 }
7118 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
7119 serializer.attribute(null, "enabled",
7120 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED
7121 ? "true" : "false");
7122 }
7123 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) {
7124 serializer.attribute(null, "installStatus", "false");
7125 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007126 if (pkg.installerPackageName != null) {
7127 serializer.attribute(null, "installer", pkg.installerPackageName);
7128 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007129 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
7130 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
7131 serializer.startTag(null, "perms");
7132 if (pkg.sharedUser == null) {
7133 // If this is a shared user, the permissions will
7134 // be written there. We still need to write an
7135 // empty permissions list so permissionsFixed will
7136 // be set.
7137 for (final String name : pkg.grantedPermissions) {
7138 serializer.startTag(null, "item");
7139 serializer.attribute(null, "name", name);
7140 serializer.endTag(null, "item");
7141 }
7142 }
7143 serializer.endTag(null, "perms");
7144 }
7145 if (pkg.disabledComponents.size() > 0) {
7146 serializer.startTag(null, "disabled-components");
7147 for (final String name : pkg.disabledComponents) {
7148 serializer.startTag(null, "item");
7149 serializer.attribute(null, "name", name);
7150 serializer.endTag(null, "item");
7151 }
7152 serializer.endTag(null, "disabled-components");
7153 }
7154 if (pkg.enabledComponents.size() > 0) {
7155 serializer.startTag(null, "enabled-components");
7156 for (final String name : pkg.enabledComponents) {
7157 serializer.startTag(null, "item");
7158 serializer.attribute(null, "name", name);
7159 serializer.endTag(null, "item");
7160 }
7161 serializer.endTag(null, "enabled-components");
7162 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 serializer.endTag(null, "package");
7165 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 void writePermission(XmlSerializer serializer, BasePermission bp)
7168 throws XmlPullParserException, java.io.IOException {
7169 if (bp.type != BasePermission.TYPE_BUILTIN
7170 && bp.sourcePackage != null) {
7171 serializer.startTag(null, "item");
7172 serializer.attribute(null, "name", bp.name);
7173 serializer.attribute(null, "package", bp.sourcePackage);
7174 if (DEBUG_SETTINGS) Log.v(TAG,
7175 "Writing perm: name=" + bp.name + " type=" + bp.type);
7176 if (bp.type == BasePermission.TYPE_DYNAMIC) {
7177 PermissionInfo pi = bp.perm != null ? bp.perm.info
7178 : bp.pendingInfo;
7179 if (pi != null) {
7180 serializer.attribute(null, "type", "dynamic");
7181 if (pi.icon != 0) {
7182 serializer.attribute(null, "icon",
7183 Integer.toString(pi.icon));
7184 }
7185 if (pi.nonLocalizedLabel != null) {
7186 serializer.attribute(null, "label",
7187 pi.nonLocalizedLabel.toString());
7188 }
7189 if (pi.protectionLevel !=
7190 PermissionInfo.PROTECTION_NORMAL) {
7191 serializer.attribute(null, "protection",
7192 Integer.toString(pi.protectionLevel));
7193 }
7194 }
7195 }
7196 serializer.endTag(null, "item");
7197 }
7198 }
7199
7200 String getReadMessagesLP() {
7201 return mReadMessages.toString();
7202 }
7203
Oscar Montemayora8529f62009-11-18 10:14:20 -08007204 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 HashSet<String> kList = new HashSet<String>(mPackages.keySet());
7206 Iterator<String> its = kList.iterator();
Oscar Montemayora8529f62009-11-18 10:14:20 -08007207 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 while(its.hasNext()) {
7209 String key = its.next();
7210 PackageSetting ps = mPackages.get(key);
7211 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) {
Oscar Montemayora8529f62009-11-18 10:14:20 -08007212 ret.add(ps);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 }
7214 }
7215 return ret;
7216 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007218 boolean readLP() {
7219 FileInputStream str = null;
7220 if (mBackupSettingsFilename.exists()) {
7221 try {
7222 str = new FileInputStream(mBackupSettingsFilename);
7223 mReadMessages.append("Reading from backup settings file\n");
7224 Log.i(TAG, "Reading from backup settings file!");
Suchi Amalapurapu14e833f2009-10-20 11:27:32 -07007225 if (mSettingsFilename.exists()) {
7226 // If both the backup and settings file exist, we
7227 // ignore the settings since it might have been
7228 // corrupted.
7229 Log.w(TAG, "Cleaning up settings file " + mSettingsFilename);
7230 mSettingsFilename.delete();
7231 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 } catch (java.io.IOException e) {
7233 // We'll try for the normal settings file.
7234 }
7235 }
7236
7237 mPastSignatures.clear();
7238
7239 try {
7240 if (str == null) {
7241 if (!mSettingsFilename.exists()) {
7242 mReadMessages.append("No settings file found\n");
7243 Log.i(TAG, "No current settings file!");
7244 return false;
7245 }
7246 str = new FileInputStream(mSettingsFilename);
7247 }
7248 XmlPullParser parser = Xml.newPullParser();
7249 parser.setInput(str, null);
7250
7251 int type;
7252 while ((type=parser.next()) != XmlPullParser.START_TAG
7253 && type != XmlPullParser.END_DOCUMENT) {
7254 ;
7255 }
7256
7257 if (type != XmlPullParser.START_TAG) {
7258 mReadMessages.append("No start tag found in settings file\n");
7259 Log.e(TAG, "No start tag found in package manager settings");
7260 return false;
7261 }
7262
7263 int outerDepth = parser.getDepth();
7264 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7265 && (type != XmlPullParser.END_TAG
7266 || parser.getDepth() > outerDepth)) {
7267 if (type == XmlPullParser.END_TAG
7268 || type == XmlPullParser.TEXT) {
7269 continue;
7270 }
7271
7272 String tagName = parser.getName();
7273 if (tagName.equals("package")) {
7274 readPackageLP(parser);
7275 } else if (tagName.equals("permissions")) {
7276 readPermissionsLP(mPermissions, parser);
7277 } else if (tagName.equals("permission-trees")) {
7278 readPermissionsLP(mPermissionTrees, parser);
7279 } else if (tagName.equals("shared-user")) {
7280 readSharedUserLP(parser);
7281 } else if (tagName.equals("preferred-packages")) {
Dianne Hackborna7ca0e52009-12-01 14:31:55 -08007282 // no longer used.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 } else if (tagName.equals("preferred-activities")) {
7284 readPreferredActivitiesLP(parser);
7285 } else if(tagName.equals("updated-package")) {
7286 readDisabledSysPackageLP(parser);
7287 } else {
7288 Log.w(TAG, "Unknown element under <packages>: "
7289 + parser.getName());
7290 XmlUtils.skipCurrentTag(parser);
7291 }
7292 }
7293
7294 str.close();
7295
7296 } catch(XmlPullParserException e) {
7297 mReadMessages.append("Error reading: " + e.toString());
7298 Log.e(TAG, "Error reading package manager settings", e);
7299
7300 } catch(java.io.IOException e) {
7301 mReadMessages.append("Error reading: " + e.toString());
7302 Log.e(TAG, "Error reading package manager settings", e);
7303
7304 }
7305
7306 int N = mPendingPackages.size();
7307 for (int i=0; i<N; i++) {
7308 final PendingPackage pp = mPendingPackages.get(i);
7309 Object idObj = getUserIdLP(pp.sharedId);
7310 if (idObj != null && idObj instanceof SharedUserSetting) {
7311 PackageSetting p = getPackageLP(pp.name,
7312 (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007313 pp.versionCode, pp.pkgFlags, true, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 if (p == null) {
7315 Log.w(TAG, "Unable to create application package for "
7316 + pp.name);
7317 continue;
7318 }
7319 p.copyFrom(pp);
7320 } else if (idObj != null) {
7321 String msg = "Bad package setting: package " + pp.name
7322 + " has shared uid " + pp.sharedId
7323 + " that is not a shared uid\n";
7324 mReadMessages.append(msg);
7325 Log.e(TAG, msg);
7326 } else {
7327 String msg = "Bad package setting: package " + pp.name
7328 + " has shared uid " + pp.sharedId
7329 + " that is not defined\n";
7330 mReadMessages.append(msg);
7331 Log.e(TAG, msg);
7332 }
7333 }
7334 mPendingPackages.clear();
7335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007336 mReadMessages.append("Read completed successfully: "
7337 + mPackages.size() + " packages, "
7338 + mSharedUsers.size() + " shared uids\n");
7339
7340 return true;
7341 }
7342
7343 private int readInt(XmlPullParser parser, String ns, String name,
7344 int defValue) {
7345 String v = parser.getAttributeValue(ns, name);
7346 try {
7347 if (v == null) {
7348 return defValue;
7349 }
7350 return Integer.parseInt(v);
7351 } catch (NumberFormatException e) {
7352 reportSettingsProblem(Log.WARN,
7353 "Error in package manager settings: attribute " +
7354 name + " has bad integer value " + v + " at "
7355 + parser.getPositionDescription());
7356 }
7357 return defValue;
7358 }
7359
7360 private void readPermissionsLP(HashMap<String, BasePermission> out,
7361 XmlPullParser parser)
7362 throws IOException, XmlPullParserException {
7363 int outerDepth = parser.getDepth();
7364 int type;
7365 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7366 && (type != XmlPullParser.END_TAG
7367 || parser.getDepth() > outerDepth)) {
7368 if (type == XmlPullParser.END_TAG
7369 || type == XmlPullParser.TEXT) {
7370 continue;
7371 }
7372
7373 String tagName = parser.getName();
7374 if (tagName.equals("item")) {
7375 String name = parser.getAttributeValue(null, "name");
7376 String sourcePackage = parser.getAttributeValue(null, "package");
7377 String ptype = parser.getAttributeValue(null, "type");
7378 if (name != null && sourcePackage != null) {
7379 boolean dynamic = "dynamic".equals(ptype);
7380 BasePermission bp = new BasePermission(name, sourcePackage,
7381 dynamic
7382 ? BasePermission.TYPE_DYNAMIC
7383 : BasePermission.TYPE_NORMAL);
7384 if (dynamic) {
7385 PermissionInfo pi = new PermissionInfo();
7386 pi.packageName = sourcePackage.intern();
7387 pi.name = name.intern();
7388 pi.icon = readInt(parser, null, "icon", 0);
7389 pi.nonLocalizedLabel = parser.getAttributeValue(
7390 null, "label");
7391 pi.protectionLevel = readInt(parser, null, "protection",
7392 PermissionInfo.PROTECTION_NORMAL);
7393 bp.pendingInfo = pi;
7394 }
7395 out.put(bp.name, bp);
7396 } else {
7397 reportSettingsProblem(Log.WARN,
7398 "Error in package manager settings: permissions has"
7399 + " no name at " + parser.getPositionDescription());
7400 }
7401 } else {
7402 reportSettingsProblem(Log.WARN,
7403 "Unknown element reading permissions: "
7404 + parser.getName() + " at "
7405 + parser.getPositionDescription());
7406 }
7407 XmlUtils.skipCurrentTag(parser);
7408 }
7409 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007411 private void readDisabledSysPackageLP(XmlPullParser parser)
7412 throws XmlPullParserException, IOException {
7413 String name = parser.getAttributeValue(null, "name");
7414 String codePathStr = parser.getAttributeValue(null, "codePath");
7415 String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
7416 if(resourcePathStr == null) {
7417 resourcePathStr = codePathStr;
7418 }
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007419 String version = parser.getAttributeValue(null, "version");
7420 int versionCode = 0;
7421 if (version != null) {
7422 try {
7423 versionCode = Integer.parseInt(version);
7424 } catch (NumberFormatException e) {
7425 }
7426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007428 int pkgFlags = 0;
7429 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007430 PackageSetting ps = new PackageSetting(name,
7431 new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007432 new File(resourcePathStr), versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007433 String timeStampStr = parser.getAttributeValue(null, "ts");
7434 if (timeStampStr != null) {
7435 try {
7436 long timeStamp = Long.parseLong(timeStampStr);
7437 ps.setTimeStamp(timeStamp, timeStampStr);
7438 } catch (NumberFormatException e) {
7439 }
7440 }
7441 String idStr = parser.getAttributeValue(null, "userId");
7442 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0;
7443 if(ps.userId <= 0) {
7444 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7445 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
7446 }
7447 int outerDepth = parser.getDepth();
7448 int type;
7449 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7450 && (type != XmlPullParser.END_TAG
7451 || parser.getDepth() > outerDepth)) {
7452 if (type == XmlPullParser.END_TAG
7453 || type == XmlPullParser.TEXT) {
7454 continue;
7455 }
7456
7457 String tagName = parser.getName();
7458 if (tagName.equals("perms")) {
7459 readGrantedPermissionsLP(parser,
7460 ps.grantedPermissions);
7461 } else {
7462 reportSettingsProblem(Log.WARN,
7463 "Unknown element under <updated-package>: "
7464 + parser.getName());
7465 XmlUtils.skipCurrentTag(parser);
7466 }
7467 }
7468 mDisabledSysPackages.put(name, ps);
7469 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 private void readPackageLP(XmlPullParser parser)
7472 throws XmlPullParserException, IOException {
7473 String name = null;
7474 String idStr = null;
7475 String sharedIdStr = null;
7476 String codePathStr = null;
7477 String resourcePathStr = null;
7478 String systemStr = null;
Jacek Surazski65e13172009-04-28 15:26:38 +02007479 String installerPackageName = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007480 int pkgFlags = 0;
7481 String timeStampStr;
7482 long timeStamp = 0;
7483 PackageSettingBase packageSetting = null;
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007484 String version = null;
7485 int versionCode = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 try {
7487 name = parser.getAttributeValue(null, "name");
7488 idStr = parser.getAttributeValue(null, "userId");
7489 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
7490 codePathStr = parser.getAttributeValue(null, "codePath");
7491 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007492 version = parser.getAttributeValue(null, "version");
7493 if (version != null) {
7494 try {
7495 versionCode = Integer.parseInt(version);
7496 } catch (NumberFormatException e) {
7497 }
7498 }
Jacek Surazski65e13172009-04-28 15:26:38 +02007499 installerPackageName = parser.getAttributeValue(null, "installer");
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007500
7501 systemStr = parser.getAttributeValue(null, "flags");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 if (systemStr != null) {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007503 try {
7504 pkgFlags = Integer.parseInt(systemStr);
7505 } catch (NumberFormatException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 }
7507 } else {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007508 // For backward compatibility
7509 systemStr = parser.getAttributeValue(null, "system");
7510 if (systemStr != null) {
7511 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0;
7512 } else {
7513 // Old settings that don't specify system... just treat
7514 // them as system, good enough.
7515 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7516 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007517 }
7518 timeStampStr = parser.getAttributeValue(null, "ts");
7519 if (timeStampStr != null) {
7520 try {
7521 timeStamp = Long.parseLong(timeStampStr);
7522 } catch (NumberFormatException e) {
7523 }
7524 }
7525 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
7526 + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
7527 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7528 if (resourcePathStr == null) {
7529 resourcePathStr = codePathStr;
7530 }
7531 if (name == null) {
7532 reportSettingsProblem(Log.WARN,
7533 "Error in package manager settings: <package> has no name at "
7534 + parser.getPositionDescription());
7535 } else if (codePathStr == null) {
7536 reportSettingsProblem(Log.WARN,
7537 "Error in package manager settings: <package> has no codePath at "
7538 + parser.getPositionDescription());
7539 } else if (userId > 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007540 packageSetting = addPackageLP(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007541 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7543 + ": userId=" + userId + " pkg=" + packageSetting);
7544 if (packageSetting == null) {
7545 reportSettingsProblem(Log.ERROR,
7546 "Failure adding uid " + userId
7547 + " while parsing settings at "
7548 + parser.getPositionDescription());
7549 } else {
7550 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7551 }
7552 } else if (sharedIdStr != null) {
7553 userId = sharedIdStr != null
7554 ? Integer.parseInt(sharedIdStr) : 0;
7555 if (userId > 0) {
7556 packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
Suchi Amalapurapuc2af31f2009-05-08 14:44:41 -07007557 new File(resourcePathStr), userId, versionCode, pkgFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558 packageSetting.setTimeStamp(timeStamp, timeStampStr);
7559 mPendingPackages.add((PendingPackage) packageSetting);
7560 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
7561 + ": sharedUserId=" + userId + " pkg="
7562 + packageSetting);
7563 } else {
7564 reportSettingsProblem(Log.WARN,
7565 "Error in package manager settings: package "
7566 + name + " has bad sharedId " + sharedIdStr
7567 + " at " + parser.getPositionDescription());
7568 }
7569 } else {
7570 reportSettingsProblem(Log.WARN,
7571 "Error in package manager settings: package "
7572 + name + " has bad userId " + idStr + " at "
7573 + parser.getPositionDescription());
7574 }
7575 } catch (NumberFormatException e) {
7576 reportSettingsProblem(Log.WARN,
7577 "Error in package manager settings: package "
7578 + name + " has bad userId " + idStr + " at "
7579 + parser.getPositionDescription());
7580 }
7581 if (packageSetting != null) {
Jacek Surazski65e13172009-04-28 15:26:38 +02007582 packageSetting.installerPackageName = installerPackageName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007583 final String enabledStr = parser.getAttributeValue(null, "enabled");
7584 if (enabledStr != null) {
7585 if (enabledStr.equalsIgnoreCase("true")) {
7586 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
7587 } else if (enabledStr.equalsIgnoreCase("false")) {
7588 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
7589 } else if (enabledStr.equalsIgnoreCase("default")) {
7590 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7591 } else {
7592 reportSettingsProblem(Log.WARN,
7593 "Error in package manager settings: package "
7594 + name + " has bad enabled value: " + idStr
7595 + " at " + parser.getPositionDescription());
7596 }
7597 } else {
7598 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
7599 }
7600 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
7601 if (installStatusStr != null) {
7602 if (installStatusStr.equalsIgnoreCase("false")) {
7603 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
7604 } else {
7605 packageSetting.installStatus = PKG_INSTALL_COMPLETE;
7606 }
7607 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007609 int outerDepth = parser.getDepth();
7610 int type;
7611 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7612 && (type != XmlPullParser.END_TAG
7613 || parser.getDepth() > outerDepth)) {
7614 if (type == XmlPullParser.END_TAG
7615 || type == XmlPullParser.TEXT) {
7616 continue;
7617 }
7618
7619 String tagName = parser.getName();
7620 if (tagName.equals("disabled-components")) {
7621 readDisabledComponentsLP(packageSetting, parser);
7622 } else if (tagName.equals("enabled-components")) {
7623 readEnabledComponentsLP(packageSetting, parser);
7624 } else if (tagName.equals("sigs")) {
7625 packageSetting.signatures.readXml(parser, mPastSignatures);
7626 } else if (tagName.equals("perms")) {
7627 readGrantedPermissionsLP(parser,
7628 packageSetting.loadedPermissions);
7629 packageSetting.permissionsFixed = true;
7630 } else {
7631 reportSettingsProblem(Log.WARN,
7632 "Unknown element under <package>: "
7633 + parser.getName());
7634 XmlUtils.skipCurrentTag(parser);
7635 }
7636 }
7637 } else {
7638 XmlUtils.skipCurrentTag(parser);
7639 }
7640 }
7641
7642 private void readDisabledComponentsLP(PackageSettingBase packageSetting,
7643 XmlPullParser parser)
7644 throws IOException, XmlPullParserException {
7645 int outerDepth = parser.getDepth();
7646 int type;
7647 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7648 && (type != XmlPullParser.END_TAG
7649 || parser.getDepth() > outerDepth)) {
7650 if (type == XmlPullParser.END_TAG
7651 || type == XmlPullParser.TEXT) {
7652 continue;
7653 }
7654
7655 String tagName = parser.getName();
7656 if (tagName.equals("item")) {
7657 String name = parser.getAttributeValue(null, "name");
7658 if (name != null) {
7659 packageSetting.disabledComponents.add(name.intern());
7660 } else {
7661 reportSettingsProblem(Log.WARN,
7662 "Error in package manager settings: <disabled-components> has"
7663 + " no name at " + parser.getPositionDescription());
7664 }
7665 } else {
7666 reportSettingsProblem(Log.WARN,
7667 "Unknown element under <disabled-components>: "
7668 + parser.getName());
7669 }
7670 XmlUtils.skipCurrentTag(parser);
7671 }
7672 }
7673
7674 private void readEnabledComponentsLP(PackageSettingBase packageSetting,
7675 XmlPullParser parser)
7676 throws IOException, XmlPullParserException {
7677 int outerDepth = parser.getDepth();
7678 int type;
7679 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7680 && (type != XmlPullParser.END_TAG
7681 || parser.getDepth() > outerDepth)) {
7682 if (type == XmlPullParser.END_TAG
7683 || type == XmlPullParser.TEXT) {
7684 continue;
7685 }
7686
7687 String tagName = parser.getName();
7688 if (tagName.equals("item")) {
7689 String name = parser.getAttributeValue(null, "name");
7690 if (name != null) {
7691 packageSetting.enabledComponents.add(name.intern());
7692 } else {
7693 reportSettingsProblem(Log.WARN,
7694 "Error in package manager settings: <enabled-components> has"
7695 + " no name at " + parser.getPositionDescription());
7696 }
7697 } else {
7698 reportSettingsProblem(Log.WARN,
7699 "Unknown element under <enabled-components>: "
7700 + parser.getName());
7701 }
7702 XmlUtils.skipCurrentTag(parser);
7703 }
7704 }
7705
7706 private void readSharedUserLP(XmlPullParser parser)
7707 throws XmlPullParserException, IOException {
7708 String name = null;
7709 String idStr = null;
7710 int pkgFlags = 0;
7711 SharedUserSetting su = null;
7712 try {
7713 name = parser.getAttributeValue(null, "name");
7714 idStr = parser.getAttributeValue(null, "userId");
7715 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
7716 if ("true".equals(parser.getAttributeValue(null, "system"))) {
7717 pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
7718 }
7719 if (name == null) {
7720 reportSettingsProblem(Log.WARN,
7721 "Error in package manager settings: <shared-user> has no name at "
7722 + parser.getPositionDescription());
7723 } else if (userId == 0) {
7724 reportSettingsProblem(Log.WARN,
7725 "Error in package manager settings: shared-user "
7726 + name + " has bad userId " + idStr + " at "
7727 + parser.getPositionDescription());
7728 } else {
7729 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
7730 reportSettingsProblem(Log.ERROR,
7731 "Occurred while parsing settings at "
7732 + parser.getPositionDescription());
7733 }
7734 }
7735 } catch (NumberFormatException e) {
7736 reportSettingsProblem(Log.WARN,
7737 "Error in package manager settings: package "
7738 + name + " has bad userId " + idStr + " at "
7739 + parser.getPositionDescription());
7740 };
7741
7742 if (su != null) {
7743 int outerDepth = parser.getDepth();
7744 int type;
7745 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7746 && (type != XmlPullParser.END_TAG
7747 || parser.getDepth() > outerDepth)) {
7748 if (type == XmlPullParser.END_TAG
7749 || type == XmlPullParser.TEXT) {
7750 continue;
7751 }
7752
7753 String tagName = parser.getName();
7754 if (tagName.equals("sigs")) {
7755 su.signatures.readXml(parser, mPastSignatures);
7756 } else if (tagName.equals("perms")) {
7757 readGrantedPermissionsLP(parser, su.loadedPermissions);
7758 } else {
7759 reportSettingsProblem(Log.WARN,
7760 "Unknown element under <shared-user>: "
7761 + parser.getName());
7762 XmlUtils.skipCurrentTag(parser);
7763 }
7764 }
7765
7766 } else {
7767 XmlUtils.skipCurrentTag(parser);
7768 }
7769 }
7770
7771 private void readGrantedPermissionsLP(XmlPullParser parser,
7772 HashSet<String> outPerms) throws IOException, XmlPullParserException {
7773 int outerDepth = parser.getDepth();
7774 int type;
7775 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7776 && (type != XmlPullParser.END_TAG
7777 || parser.getDepth() > outerDepth)) {
7778 if (type == XmlPullParser.END_TAG
7779 || type == XmlPullParser.TEXT) {
7780 continue;
7781 }
7782
7783 String tagName = parser.getName();
7784 if (tagName.equals("item")) {
7785 String name = parser.getAttributeValue(null, "name");
7786 if (name != null) {
7787 outPerms.add(name.intern());
7788 } else {
7789 reportSettingsProblem(Log.WARN,
7790 "Error in package manager settings: <perms> has"
7791 + " no name at " + parser.getPositionDescription());
7792 }
7793 } else {
7794 reportSettingsProblem(Log.WARN,
7795 "Unknown element under <perms>: "
7796 + parser.getName());
7797 }
7798 XmlUtils.skipCurrentTag(parser);
7799 }
7800 }
7801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 private void readPreferredActivitiesLP(XmlPullParser parser)
7803 throws XmlPullParserException, IOException {
7804 int outerDepth = parser.getDepth();
7805 int type;
7806 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
7807 && (type != XmlPullParser.END_TAG
7808 || parser.getDepth() > outerDepth)) {
7809 if (type == XmlPullParser.END_TAG
7810 || type == XmlPullParser.TEXT) {
7811 continue;
7812 }
7813
7814 String tagName = parser.getName();
7815 if (tagName.equals("item")) {
7816 PreferredActivity pa = new PreferredActivity(parser);
7817 if (pa.mParseError == null) {
7818 mPreferredActivities.addFilter(pa);
7819 } else {
7820 reportSettingsProblem(Log.WARN,
7821 "Error in package manager settings: <preferred-activity> "
7822 + pa.mParseError + " at "
7823 + parser.getPositionDescription());
7824 }
7825 } else {
7826 reportSettingsProblem(Log.WARN,
7827 "Unknown element under <preferred-activities>: "
7828 + parser.getName());
7829 XmlUtils.skipCurrentTag(parser);
7830 }
7831 }
7832 }
7833
7834 // Returns -1 if we could not find an available UserId to assign
7835 private int newUserIdLP(Object obj) {
7836 // Let's be stupidly inefficient for now...
7837 final int N = mUserIds.size();
7838 for (int i=0; i<N; i++) {
7839 if (mUserIds.get(i) == null) {
7840 mUserIds.set(i, obj);
7841 return FIRST_APPLICATION_UID + i;
7842 }
7843 }
7844
7845 // None left?
7846 if (N >= MAX_APPLICATION_UIDS) {
7847 return -1;
7848 }
7849
7850 mUserIds.add(obj);
7851 return FIRST_APPLICATION_UID + N;
7852 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 public PackageSetting getDisabledSystemPkg(String name) {
7855 synchronized(mPackages) {
7856 PackageSetting ps = mDisabledSysPackages.get(name);
7857 return ps;
7858 }
7859 }
7860
7861 boolean isEnabledLP(ComponentInfo componentInfo, int flags) {
7862 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
7863 if (Config.LOGV) {
7864 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName
7865 + " componentName = " + componentInfo.name);
7866 Log.v(TAG, "enabledComponents: "
7867 + Arrays.toString(packageSettings.enabledComponents.toArray()));
7868 Log.v(TAG, "disabledComponents: "
7869 + Arrays.toString(packageSettings.disabledComponents.toArray()));
7870 }
7871 return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
7872 || ((componentInfo.enabled
7873 && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
7874 || (componentInfo.applicationInfo.enabled
7875 && packageSettings.enabled != COMPONENT_ENABLED_STATE_DISABLED))
7876 && !packageSettings.disabledComponents.contains(componentInfo.name))
7877 || packageSettings.enabledComponents.contains(componentInfo.name));
7878 }
7879 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007880
7881 // ------- apps on sdcard specific code -------
7882 static final boolean DEBUG_SD_INSTALL = false;
Oscar Montemayord02546b2010-01-14 16:38:40 -08007883 final private String mSdEncryptKey = "AppsOnSD";
Oscar Montemayor462f0372010-01-14 16:38:40 -08007884 final private String mSdEncryptAlg = "AES";
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007885 private boolean mMediaMounted = false;
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007886 private static final int MAX_CONTAINERS = 250;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007887
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007888
7889 static MountService getMountService() {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007890 return (MountService) ServiceManager.getService("mount");
7891 }
7892
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007893 private String getEncryptKey() {
7894 try {
7895 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7896 if (sdEncKey == null) {
7897 sdEncKey = SystemKeyStore.getInstance().
7898 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
7899 if (sdEncKey == null) {
7900 Log.e(TAG, "Failed to create encryption keys");
7901 return null;
7902 }
7903 }
7904 return sdEncKey;
7905 } catch (NoSuchAlgorithmException nsae) {
7906 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
7907 return null;
7908 }
7909 }
7910
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007911 private String createSdDir(File tmpPackageFile, String pkgName) {
7912 // Create mount point via MountService
7913 MountService mountService = getMountService();
7914 long len = tmpPackageFile.length();
7915 int mbLen = (int) (len/(1024*1024));
7916 if ((len - (mbLen * 1024 * 1024)) > 0) {
7917 mbLen++;
7918 }
7919 if (DEBUG_SD_INSTALL) Log.i(TAG, "mbLen="+mbLen);
7920 String cachePath = null;
Oscar Montemayord02546b2010-01-14 16:38:40 -08007921 String sdEncKey;
7922 try {
7923 sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7924 if (sdEncKey == null) {
7925 sdEncKey = SystemKeyStore.getInstance().
7926 generateNewKeyHexString(128, mSdEncryptAlg, mSdEncryptKey);
7927 if (sdEncKey == null) {
7928 Log.e(TAG, "Failed to create encryption keys for package: " + pkgName + ".");
7929 return null;
7930 }
7931 }
7932 } catch (NoSuchAlgorithmException nsae) {
7933 Log.e(TAG, "Failed to create encryption keys with exception: " + nsae);
7934 return null;
7935 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007936 try {
7937 cachePath = mountService.createSecureContainer(pkgName,
7938 mbLen,
Oscar Montemayord02546b2010-01-14 16:38:40 -08007939 "vfat", sdEncKey, Process.SYSTEM_UID);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007940 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install " + pkgName + ", cachePath =" + cachePath);
7941 return cachePath;
7942 } catch(IllegalStateException e) {
7943 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7944 }
7945 // TODO just fail here and let the user delete later on.
7946 try {
7947 mountService.destroySecureContainer(pkgName);
7948 if (DEBUG_SD_INSTALL) Log.i(TAG, "Destroying cache for " + pkgName + ", cachePath =" + cachePath);
7949 } catch(IllegalStateException e) {
7950 Log.e(TAG, "Failed to destroy existing cache: " + e);
7951 return null;
7952 }
7953 try {
7954 cachePath = mountService.createSecureContainer(pkgName,
7955 mbLen,
Oscar Montemayord02546b2010-01-14 16:38:40 -08007956 "vfat", sdEncKey, Process.SYSTEM_UID);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007957 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to install again " + pkgName + ", cachePath =" + cachePath);
7958 return cachePath;
7959 } catch(IllegalStateException e) {
7960 Log.e(TAG, "Failed to create storage on sdcard with exception: " + e);
7961 return null;
7962 }
7963 }
7964
7965 private String mountSdDir(String pkgName, int ownerUid) {
Oscar Montemayord02546b2010-01-14 16:38:40 -08007966 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString(mSdEncryptKey);
7967 if (sdEncKey == null) {
7968 Log.e(TAG, "Failed to retrieve encryption keys to mount package code: " + pkgName + ".");
7969 return null;
7970 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007971 try {
Oscar Montemayord02546b2010-01-14 16:38:40 -08007972 return getMountService().mountSecureContainer(pkgName, sdEncKey, ownerUid);
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007973 } catch (IllegalStateException e) {
7974 Log.i(TAG, "Failed to mount container for pkg : " + pkgName + " exception : " + e);
7975 }
7976 return null;
7977 }
7978
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007979 private boolean unMountSdDir(String pkgName) {
7980 // STOPSHIP unmount directory
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08007981 try {
7982 getMountService().unmountSecureContainer(pkgName);
7983 return true;
7984 } catch (IllegalStateException e) {
7985 Log.e(TAG, "Failed to unmount : " + pkgName + " with exception " + e);
7986 }
7987 return false;
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08007988 }
7989
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08007990 private String getSdDir(String pkgName) {
7991 String cachePath = null;
7992 try {
7993 cachePath = getMountService().getSecureContainerPath(pkgName);
7994 } catch (IllegalStateException e) {
7995 Log.e(TAG, "Failed to retrieve secure container path for pkg : " + pkgName + " with exception " + e);
7996 }
7997 return cachePath;
7998 }
7999
8000 private boolean finalizeSdDir(String pkgName) {
8001 try {
8002 getMountService().finalizeSecureContainer(pkgName);
8003 return true;
8004 } catch (IllegalStateException e) {
8005 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
8006 return false;
8007 }
8008 }
8009
8010 private boolean destroySdDir(String pkgName) {
8011 try {
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008012 // We need to destroy right away
8013 getMountService().destroySecureContainer(pkgName);
8014 return true;
8015 } catch (IllegalStateException e) {
8016 Log.i(TAG, "Failed to destroy container for pkg : " + pkgName);
8017 return false;
8018 }
8019 }
8020
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008021 static String[] getSecureContainerList() {
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008022 try {
8023 return getMountService().getSecureContainerList();
8024 } catch (IllegalStateException e) {
8025 Log.i(TAG, "Failed to getSecureContainerList");
8026 }
8027 return null;
8028 }
8029
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008030 static String getTempContainerId() {
8031 String prefix = "smdl1tmp";
8032 int tmpIdx = 1;
8033 String list[] = getSecureContainerList();
8034 if (list != null) {
8035 int idx = 0;
8036 int idList[] = new int[MAX_CONTAINERS];
8037 boolean neverFound = true;
8038 for (String name : list) {
8039 // Ignore null entries
8040 if (name == null) {
8041 continue;
8042 }
8043 int sidx = name.indexOf(prefix);
8044 if (sidx == -1) {
8045 // Not a temp file. just ignore
8046 continue;
8047 }
8048 String subStr = name.substring(sidx + prefix.length());
8049 idList[idx] = -1;
8050 if (subStr != null) {
8051 try {
8052 int cid = Integer.parseInt(subStr);
8053 idList[idx++] = cid;
8054 neverFound = false;
8055 } catch (NumberFormatException e) {
8056 }
8057 }
8058 }
8059 if (!neverFound) {
8060 // Sort idList
8061 Arrays.sort(idList);
8062 for (int j = 1; j <= idList.length; j++) {
8063 if (idList[j-1] != j) {
8064 tmpIdx = j;
8065 break;
8066 }
8067 }
8068 }
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008069 }
Suchi Amalapurapuc028be42010-01-25 12:19:12 -08008070 return prefix + tmpIdx;
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008071 }
8072
Suchi Amalapurapufd3530f2010-01-18 00:15:59 -08008073 public void updateExternalMediaStatus(final boolean mediaStatus) {
8074 if (mediaStatus == mMediaMounted) {
8075 return;
8076 }
8077 mMediaMounted = mediaStatus;
8078 // Queue up an async operation since the package installation may take a little while.
8079 mHandler.post(new Runnable() {
8080 public void run() {
8081 mHandler.removeCallbacks(this);
8082 final String list[] = getSecureContainerList();
8083 if (list == null || list.length == 0) {
8084 return;
8085 }
8086 for (int i = 0; i < list.length; i++) {
8087 String mountPkg = list[i];
8088 // TODO compare with default package
8089 synchronized (mPackages) {
8090 PackageSetting ps = mSettings.mPackages.get(mountPkg);
8091 if (ps != null && (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
8092 if (mediaStatus) {
8093 String pkgPath = getSdDir(mountPkg);
8094 if (pkgPath == null) {
8095 continue;
8096 }
8097 pkgPath = ps.codePathString;
8098 int parseFlags = PackageParser.PARSE_CHATTY |
8099 PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8100 PackageParser pp = new PackageParser(pkgPath);
8101 pp.setSeparateProcesses(mSeparateProcesses);
8102 final PackageParser.Package pkg = pp.parsePackage(new File(pkgPath),
8103 null, mMetrics, parseFlags);
8104 if (pkg == null) {
8105 Log.w(TAG, "Failed to install package : " + mountPkg + " from sd card");
8106 continue;
8107 }
8108 int scanMode = SCAN_MONITOR;
8109 // Scan the package
8110 if (scanPackageLI(pkg, parseFlags, scanMode) != null) {
8111 // Grant permissions
8112 grantPermissionsLP(pkg, false);
8113 // Persist settings
8114 mSettings.writeLP();
8115 } else {
8116 Log.i(TAG, "Failed to install package: " + mountPkg + " from sdcard");
8117 }
8118 } else {
8119 // Delete package
8120 PackageRemovedInfo outInfo = new PackageRemovedInfo();
8121 boolean res = deletePackageLI(mountPkg, false, PackageManager.DONT_DELETE_DATA, outInfo);
8122 if (!res) {
8123 Log.e(TAG, "Failed to delete pkg from sdcard : " + mountPkg);
8124 }
8125 }
8126 }
8127 }
8128 }
8129 }
8130 });
Suchi Amalapurapuaf8e9f42010-01-12 10:17:28 -08008131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008132}